Ticket #32522: 32522.diff
| File 32522.diff, 105.8 KB (added by , 11 years ago) |
|---|
-
src/wp-includes/admin-bar.php
diff --git src/wp-includes/admin-bar.php src/wp-includes/admin-bar.php index a12e9c9..3a2819b 100644
function is_admin_bar_showing() { 910 910 } 911 911 } 912 912 913 if ( is_embed() ) { 914 $show_admin_bar = false; 915 } 916 913 917 /** 914 918 * Filter whether to show the admin bar. 915 919 * -
src/wp-includes/class-wp-editor.php
diff --git src/wp-includes/class-wp-editor.php src/wp-includes/class-wp-editor.php index 911aaab..ae6c0eb 100644
final class _WP_Editors { 401 401 'wplink', 402 402 'wpdialogs', 403 403 'wptextpattern', 404 'wpview' 404 'wpview', 405 'wpoembed', 405 406 ); 406 407 407 408 if ( ! self::$has_medialib ) { -
src/wp-includes/class-wp-embed.php
diff --git src/wp-includes/class-wp-embed.php src/wp-includes/class-wp-embed.php index d4b1ded..730fc4f 100644
class WP_Embed { 233 233 * Filter whether to inspect the given URL for discoverable link tags. 234 234 * 235 235 * @since 2.9.0 236 * @since 4.4.0 The default value changed to true. 236 237 * 237 238 * @see WP_oEmbed::discover() 238 239 * 239 * @param bool $enable Whether to enable `<link>` tag discovery. Default false.240 * @param bool $enable Whether to enable `<link>` tag discovery. Default true. 240 241 */ 241 $attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html') );242 $attr['discover'] = ( apply_filters( 'embed_oembed_discover', true ) ); 242 243 243 244 // Use oEmbed to get the HTML 244 245 $html = wp_oembed_get( $url, $attr ); -
new file src/wp-includes/class-wp-oembed-controller.php
diff --git src/wp-includes/class-wp-oembed-controller.php src/wp-includes/class-wp-oembed-controller.php new file mode 100644 index 0000000..0fc25ba
- + 1 <?php 2 /** 3 * WP_oEmbed_Controller class, used to provide an oEmbed endpoint. 4 * 5 * @package WordPress 6 * @subpackage Embeds 7 * @since 4.4.0 8 */ 9 10 /** 11 * oEmbed API endpoint controller. 12 * 13 * Parses the oEmbed API requests and delivers 14 * XML and JSON responses. 15 * 16 * @since 4.4.0 17 */ 18 final class WP_oEmbed_Controller { 19 /** 20 * Hook into the query parsing to detect oEmbed requests. 21 * 22 * If an oEmbed request is made, trigger the output. 23 * 24 * @since 4.4.0 25 * 26 * @param WP_Query $wp_query The WP_Query instance (passed by reference). 27 */ 28 public function parse_query( $wp_query ) { 29 if ( false === $wp_query->get( 'oembed', false ) ) { 30 return; 31 } 32 33 if ( false === $wp_query->get( 'url', false ) ) { 34 status_header( 400 ); 35 echo 'URL parameter missing'; 36 exit; 37 } 38 39 $url = esc_url_raw( get_query_var( 'url' ) ); 40 41 $format = wp_oembed_ensure_format( get_query_var( 'format' ) ); 42 43 /** 44 * Filter the maxwidth oEmbed parameter. 45 * 46 * @since 4.4.0 47 * 48 * @param int $maxwidth Maximum allowed width. Default 600. 49 */ 50 $maxwidth = apply_filters( 'oembed_default_width', 600 ); 51 $maxwidth = absint( get_query_var( 'maxwidth', $maxwidth ) ); 52 53 $callback = get_query_var( '_jsonp', false ); 54 55 $request = array( 56 'url' => $url, 57 'format' => $format, 58 'maxwidth' => $maxwidth, 59 'callback' => $callback, 60 ); 61 62 echo $this->dispatch( $request ); 63 exit; 64 } 65 66 /** 67 * Handle the whole request and print the response. 68 * 69 * @since 4.4.0 70 * 71 * @param array $request The request arguments. 72 * @return string The oEmbed API response. 73 */ 74 public function dispatch( $request ) { 75 $post_id = url_to_postid( $request['url'] ); 76 77 /** 78 * Filter the determined post id. 79 * 80 * @since 4.4.0 81 * 82 * @param int $post_id The post ID. 83 * @param string $url The requestd URL. 84 */ 85 $post_id = apply_filters( 'oembed_request_post_id', $post_id, $request['url'] ); 86 87 $data = get_oembed_response_data( $post_id, $request['maxwidth'] ); 88 89 if ( false === $data ) { 90 status_header( 404 ); 91 return __( 'Invalid URL.', 'oembed-api' ); 92 } 93 94 if ( 'json' === $request['format'] ) { 95 return $this->json_response( $data, $request ); 96 } 97 98 return $this->xml_response( $data ); 99 } 100 101 /** 102 * Print the oEmbed JSON response. 103 * 104 * @since 4.4.0 105 * 106 * @param array $data The oEmbed response data. 107 * @param array $request The request arguments. 108 * @return string The JSON response data. 109 */ 110 public function json_response( $data, $request ) { 111 if ( ! is_string( $request['callback'] ) || preg_match( '/[^\w\.]/', $request['callback'] ) ) { 112 $request['callback'] = false; 113 } 114 115 $result = wp_json_encode( $data ); 116 117 // Bail if the result couldn't be JSON encoded. 118 if ( ! $result || ! is_array( $data ) || empty( $data ) ) { 119 status_header( 501 ); 120 return 'Not implemented'; 121 } 122 123 if ( ! headers_sent() ) { 124 $content_type = $request['callback'] ? 'application/javascript' : 'application/json'; 125 header( 'Content-Type: ' . $content_type . '; charset=' . get_option( 'blog_charset' ) ); 126 header( 'X-Content-Type-Options: nosniff' ); 127 } 128 129 if ( $request['callback'] ) { 130 return '/**/' . $request['callback'] . '(' . $result . ')'; 131 } 132 133 return $result; 134 } 135 136 /** 137 * Print the oEmbed XML response. 138 * 139 * @since 4.4.0 140 * 141 * @param array $data The oEmbed response data. 142 * @return string The XML response data. 143 */ 144 public function xml_response( $data ) { 145 $result = _oembed_create_xml( $data ); 146 147 // Bail if there's no XML. 148 if ( ! $result ) { 149 status_header( 501 ); 150 return 'Not implemented'; 151 } 152 153 if ( ! headers_sent() ) { 154 header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) ); 155 } 156 157 return $result; 158 } 159 } -
src/wp-includes/class-wp-rewrite.php
diff --git src/wp-includes/class-wp-rewrite.php src/wp-includes/class-wp-rewrite.php index 84a57c8..b7b3753 100644
class WP_Rewrite { 861 861 $trackbackregex = 'trackback/?$'; 862 862 $pageregex = $this->pagination_base . '/?([0-9]{1,})/?$'; 863 863 $commentregex = $this->comments_pagination_base . '-([0-9]{1,})/?$'; 864 $embedregex = 'embed/?$'; 864 865 865 866 //build up an array of endpoint regexes to append => queries to append 866 867 if ( $endpoints ) { … … class WP_Rewrite { 884 885 $index = $this->index; //probably 'index.php' 885 886 $feedindex = $index; 886 887 $trackbackindex = $index; 888 $embedindex = $index; 889 887 890 //build a list from the rewritecode and queryreplace arrays, that will look something like 888 891 //tagname=$matches[i] where i is the current $i 889 892 $queries = array(); … … class WP_Rewrite { 1029 1032 //create query and regex for trackback 1030 1033 $trackbackmatch = $match . $trackbackregex; 1031 1034 $trackbackquery = $trackbackindex . '?' . $query . '&tb=1'; 1035 1036 // Create query and regex for embeds. 1037 $embedmatch = $match . $embedregex; 1038 $embedquery = $embedindex . '?' . $query . '&embed=true'; 1039 1032 1040 //trim slashes from the end of the regex for this dir 1033 1041 $match = rtrim($match, '/'); 1042 1034 1043 //get rid of brackets 1035 1044 $submatchbase = str_replace( array('(', ')'), '', $match); 1036 1045 … … class WP_Rewrite { 1040 1049 $sub1feed = $sub1 . $feedregex; //and <permalink>/feed/(atom|...) 1041 1050 $sub1feed2 = $sub1 . $feedregex2; //and <permalink>/(feed|atom...) 1042 1051 $sub1comment = $sub1 . $commentregex; //and <permalink>/comment-page-xx 1052 $sub1embed = $sub1 . $embedregex; //and <permalink>/embed/... 1043 1053 1044 1054 //add another rule to match attachments in the explicit form: 1045 1055 //<permalink>/attachment/some-text … … class WP_Rewrite { 1048 1058 $sub2feed = $sub2 . $feedregex; //feeds, <permalink>/attachment/feed/(atom|...) 1049 1059 $sub2feed2 = $sub2 . $feedregex2; //and feeds again on to this <permalink>/attachment/(feed|atom...) 1050 1060 $sub2comment = $sub2 . $commentregex; //and <permalink>/comment-page-xx 1061 $sub2embed = $sub2 . $embedregex; //and <permalink>/embed/... 1051 1062 1052 1063 //create queries for these extra tag-ons we've just dealt with 1053 1064 $subquery = $index . '?attachment=' . $this->preg_index(1); 1054 1065 $subtbquery = $subquery . '&tb=1'; 1055 1066 $subfeedquery = $subquery . '&feed=' . $this->preg_index(2); 1056 1067 $subcommentquery = $subquery . '&cpage=' . $this->preg_index(2); 1068 $subembedquery = $subquery . '&embed=true'; 1057 1069 1058 1070 //do endpoints for attachments 1059 1071 if ( !empty($endpoints) ) { … … class WP_Rewrite { 1092 1104 //add trackback 1093 1105 $rewrite = array_merge(array($trackbackmatch => $trackbackquery), $rewrite); 1094 1106 1107 // add embed 1108 $rewrite = array_merge( array( $embedmatch => $embedquery ), $rewrite ); 1109 1095 1110 //add regexes/queries for attachments, attachment trackbacks and so on 1096 if ( ! $page ) //require <permalink>/attachment/stuff form for pages because of confusion with subpages 1097 $rewrite = array_merge($rewrite, array($sub1 => $subquery, $sub1tb => $subtbquery, $sub1feed => $subfeedquery, $sub1feed2 => $subfeedquery, $sub1comment => $subcommentquery)); 1098 $rewrite = array_merge(array($sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery, $sub2comment => $subcommentquery), $rewrite); 1111 if ( ! $page ) { 1112 //require <permalink>/attachment/stuff form for pages because of confusion with subpages 1113 $rewrite = array_merge( $rewrite, array($sub1 => $subquery, $sub1tb => $subtbquery, $sub1feed => $subfeedquery, $sub1feed2 => $subfeedquery, $sub1comment => $subcommentquery, $sub1embed => $subembedquery ) ); 1114 } 1115 1116 $rewrite = array_merge( array( $sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery, $sub2comment => $subcommentquery, $sub2embed => $subembedquery ), $rewrite ); 1099 1117 } 1100 1118 } //if($num_toks) 1101 1119 //add the rules for this dir to the accumulating $post_rewrite -
src/wp-includes/class-wp.php
diff --git src/wp-includes/class-wp.php src/wp-includes/class-wp.php index 4fe2757..2ed5564 100644
class WP { 15 15 * @access public 16 16 * @var array 17 17 */ 18 public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'title' );18 public $public_query_vars = array('m', 'p', 'posts', 'w', 'cat', 'withcomments', 'withoutcomments', 's', 'search', 'exact', 'sentence', 'calendar', 'page', 'paged', 'more', 'tb', 'pb', 'author', 'order', 'orderby', 'year', 'monthnum', 'day', 'hour', 'minute', 'second', 'name', 'category_name', 'tag', 'feed', 'author_name', 'static', 'pagename', 'page_id', 'error', 'comments_popup', 'attachment', 'attachment_id', 'subpost', 'subpost_id', 'preview', 'robots', 'taxonomy', 'term', 'cpage', 'post_type', 'title', 'embed', 'oembed', 'format', 'url', '_jsonp', 'maxwidth'); 19 19 20 20 /** 21 21 * Private query variables. -
src/wp-includes/default-filters.php
diff --git src/wp-includes/default-filters.php src/wp-includes/default-filters.php index 30974c2..c1dab72 100644
add_action( 'media_buttons', 'media_buttons' ); 421 421 add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 ); 422 422 add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 ); 423 423 424 // Embeds 425 426 add_action( 'parse_query', 'wp_oembed_parse_query' ); 427 428 add_action( 'wp_head', 'wp_oembed_add_discovery_links' ); 429 add_action( 'wp_head', 'wp_oembed_add_host_js' ); 430 431 add_action( 'oembed_head', 'print_emoji_detection_script' ); 432 add_action( 'oembed_head', 'print_emoji_styles' ); 433 add_action( 'oembed_head', 'wp_print_head_scripts', 20 ); 434 add_action( 'oembed_head', 'wp_print_styles', 20 ); 435 add_action( 'oembed_head', 'wp_no_robots' ); 436 add_action( 'oembed_head', 'rel_canonical' ); 437 add_action( 'oembed_head', 'locale_stylesheet' ); 438 439 add_action( 'oembed_footer', 'wp_print_footer_scripts', 20 ); 440 441 add_filter( 'excerpt_more', 'wp_oembed_excerpt_more', 20 ); 442 add_filter( 'the_excerpt_embed', 'wptexturize' ); 443 add_filter( 'the_excerpt_embed', 'convert_chars' ); 444 add_filter( 'the_excerpt_embed', 'wpautop' ); 445 add_filter( 'the_excerpt_embed', 'shortcode_unautop' ); 446 add_filter( 'the_excerpt_embed', 'wp_oembed_excerpt_attachment' ); 447 448 add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 ); 449 add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 ); 450 424 451 unset( $filter, $action ); -
new file src/wp-includes/embed-template.php
diff --git src/wp-includes/embed-template.php src/wp-includes/embed-template.php new file mode 100644 index 0000000..73ba2fd
- + 1 <?php 2 /** 3 * Contains the post embed template. 4 * 5 * When a post is embedded in an iframe, this file is used to 6 * create the output. 7 * 8 * @package WordPress 9 * @subpackage oEmbed 10 * @since 4.4.0 11 */ 12 13 if ( ! headers_sent() ) { 14 header( 'X-WP-oembed: true' ); 15 } 16 17 wp_enqueue_style( 'open-sans' ); 18 19 ?> 20 <!DOCTYPE html> 21 <html <?php language_attributes(); ?>> 22 <head> 23 <title><?php wp_title( '-', true, 'right' ); ?></title> 24 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 25 <style type="text/css"> 26 html, body { 27 padding: 0; 28 margin: 0; 29 } 30 31 body { 32 font-family: sans-serif; 33 } 34 35 /* Text meant only for screen readers */ 36 .screen-reader-text { 37 clip: rect(1px, 1px, 1px, 1px); 38 height: 1px; 39 overflow: hidden; 40 position: absolute !important; 41 width: 1px; 42 } 43 44 /* Dashicons */ 45 .dashicons { 46 display: inline-block; 47 width: 20px; 48 height: 20px; 49 background-color: transparent; 50 background-repeat: no-repeat; 51 background-size: 20px; 52 background-position: center; 53 -webkit-transition: background .1s ease-in; 54 transition: background .1s ease-in; 55 position: relative; 56 top: 5px; 57 } 58 59 .dashicons-no { 60 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"); 61 } 62 63 .dashicons-admin-comments { 64 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"); 65 } 66 67 .wp-embed-comments a:hover .dashicons-admin-comments { 68 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"); 69 } 70 71 .dashicons-share { 72 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"); 73 } 74 75 .wp-embed-share-dialog-open:hover .dashicons-share { 76 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"); 77 } 78 79 .wp-embed { 80 width: 100%; 81 padding: 25px; 82 font: 400 14px/1.5 'Open Sans', sans-serif; 83 color: #82878c; 84 background: white; 85 border: 1px solid #e5e5e5; 86 -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); 87 box-shadow: 0 1px 1px rgba(0, 0, 0, .05); 88 box-sizing: border-box; 89 /* Clearfix */ 90 overflow: auto; 91 zoom: 1; 92 } 93 94 .wp-embed a { 95 color: #82878c; 96 text-decoration: none; 97 } 98 99 .wp-embed a:hover { 100 text-decoration: underline; 101 } 102 103 .wp-embed-featured-image { 104 margin-bottom: 20px; 105 } 106 107 .wp-embed-featured-image img { 108 width: 100%; 109 height: auto; 110 border: none; 111 } 112 113 .wp-embed-featured-image.square { 114 float: left; 115 max-width: 160px; 116 margin-right: 20px; 117 } 118 119 .wp-embed p { 120 margin: 0; 121 } 122 123 p.wp-embed-heading { 124 margin: 0 0 15px; 125 font-weight: bold; 126 font-size: 22px; 127 line-height: 1.3; 128 } 129 130 .wp-embed-heading a { 131 color: #32373c; 132 } 133 134 .wp-embed .wp-embed-more { 135 color: #b4b9be; 136 } 137 138 .wp-embed-footer { 139 display: table; 140 width: 100%; 141 margin-top: 30px; 142 } 143 144 .wp-embed-site-icon { 145 position: absolute; 146 top: 50%; 147 left: 0; 148 -webkit-transform: translateY(-50%); 149 transform: translateY(-50%); 150 height: 25px; 151 width: 25px; 152 border: 0; 153 } 154 155 .wp-embed-site-title { 156 font-weight: bold; 157 line-height: 25px; 158 } 159 160 .wp-embed-site-title a { 161 position: relative; 162 display: inline-block; 163 padding-left: 35px; 164 } 165 166 .wp-embed-site-title, 167 .wp-embed-meta { 168 display: table-cell; 169 } 170 171 .wp-embed-meta { 172 text-align: right; 173 white-space: nowrap; 174 vertical-align: middle; 175 } 176 177 .wp-embed-comments, 178 .wp-embed-share { 179 display: inline; 180 } 181 182 .wp-embed-meta a:hover { 183 text-decoration: none; 184 color: #0073aa; 185 } 186 187 .wp-embed-comments a { 188 line-height: 25px; 189 display: inline-block; 190 } 191 192 .wp-embed-comments + .wp-embed-share { 193 margin-left: 10px; 194 } 195 196 .wp-embed-share-dialog { 197 position: absolute; 198 top: 0; 199 left: 0; 200 right: 0; 201 bottom: 0; 202 background-color: rgba(10, 10, 10, 0.9); 203 color: #fff; 204 opacity: 1; 205 transition: opacity .25s ease-in-out; 206 -moz-transition: opacity .25s ease-in-out; 207 -webkit-transition: opacity .25s ease-in-out; 208 } 209 210 .wp-embed-share-dialog.hidden { 211 opacity: 0; 212 visibility: hidden; 213 } 214 215 .wp-embed-share-dialog-open, 216 .wp-embed-share-dialog-close { 217 margin: -8px 0 0; 218 padding: 0; 219 background: transparent; 220 border: none; 221 cursor: pointer; 222 outline: none; 223 } 224 225 .wp-embed-share-dialog-open .dashicons, 226 .wp-embed-share-dialog-close .dashicons { 227 padding: 4px; 228 } 229 230 .wp-embed-share-dialog-open .dashicons { 231 top: 8px; 232 } 233 234 .wp-embed-share-dialog-open:focus .dashicons, 235 .wp-embed-share-dialog-close:focus .dashicons { 236 -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); 237 box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); 238 -webkit-border-radius: 100%; 239 border-radius: 100%; 240 } 241 242 .wp-embed-share-dialog-close { 243 position: absolute; 244 top: 20px; 245 right: 20px; 246 font-size: 22px; 247 } 248 249 .wp-embed-share-dialog-close:hover { 250 text-decoration: none; 251 } 252 253 .wp-embed-share-dialog-close .dashicons { 254 height: 24px; 255 width: 24px; 256 background-size: 24px; 257 } 258 259 .wp-embed-share-dialog-content { 260 height: 100%; 261 -webkit-transform-style: preserve-3d; 262 -moz-transform-style: preserve-3d; 263 transform-style: preserve-3d; 264 overflow: hidden; 265 } 266 267 .wp-embed-share-dialog-text { 268 margin-top: 25px; 269 padding: 20px; 270 } 271 272 .wp-embed-share-tabs { 273 margin: 0 0 20px; 274 padding: 0; 275 list-style: none; 276 } 277 278 .wp-embed-share-tab-button { 279 display: inline; 280 } 281 282 .wp-embed-share-tab-button button { 283 margin: 0; 284 padding: 0; 285 border: none; 286 background: transparent; 287 font-size: 16px; 288 line-height: 1.3; 289 color: #aaa; 290 cursor: pointer; 291 -webkit-transition: color .1s ease-in; 292 transition: color .1s ease-in; 293 } 294 295 .wp-embed-share-tab-button [aria-selected="true"] { 296 color: #fff; 297 } 298 299 .wp-embed-share-tab-button button:hover { 300 color: #fff; 301 } 302 303 .wp-embed-share-tab-button + .wp-embed-share-tab-button { 304 margin: 0 0 0 10px; 305 padding: 0 0 0 11px; 306 border-left: 1px solid #aaa; 307 } 308 309 .wp-embed-share-tab[aria-hidden="true"] { 310 display: none; 311 } 312 313 p.wp-embed-share-description { 314 margin: 0; 315 font-size: 14px; 316 line-height: 1; 317 font-style: italic; 318 color: #aaa; 319 } 320 321 .wp-embed-share-input { 322 box-sizing: border-box; 323 width: 100%; 324 border: none; 325 height: 28px; 326 margin: 0 0 10px 0; 327 padding: 0 5px; 328 font: 400 14px/1.5 'Open Sans', sans-serif; 329 resize: none; 330 cursor: text; 331 } 332 333 textarea.wp-embed-share-input { 334 height: 72px; 335 } 336 337 html[dir="rtl"] .wp-embed-featured-image.square { 338 float: right; 339 margin-right: 0; 340 341 margin-left: 20px; 342 } 343 344 html[dir="rtl"] .wp-embed-site-title a { 345 padding-left: 0; 346 padding-right: 35px; 347 } 348 349 html[dir="rtl"] .wp-embed-site-icon { 350 margin-right: 0; 351 margin-left: 10px; 352 left: auto; 353 right: 0; 354 } 355 356 html[dir="rtl"] .wp-embed-meta { 357 text-align: left; 358 } 359 360 html[dir="rtl"] .wp-embed-footer { 361 } 362 363 html[dir="rtl"] .wp-embed-share { 364 margin-left: 0; 365 margin-right: 10px; 366 } 367 368 html[dir="rtl"] .wp-embed-share-dialog-close { 369 right: auto; 370 left: 20px; 371 } 372 373 html[dir="rtl"] .wp-embed-share-tab-button + .wp-embed-share-tab-button { 374 margin: 0 10px 0 0; 375 padding: 0 11px 0 0; 376 border-left: none; 377 border-right: 1px solid #aaa; 378 } 379 </style> 380 <script type="text/javascript"> 381 (function ( window, document ) { 382 'use strict'; 383 384 var secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' ), 385 share_dialog, share_dialog_open, share_dialog_close, share_dialog_tabs, share_input, resizing; 386 387 function sendEmbedMessage( message, value ) { 388 window.parent.postMessage( { 389 message: message, 390 value: value, 391 secret: secret 392 }, '*' ); 393 } 394 395 function onLoad() { 396 share_dialog = document.querySelector( '.wp-embed-share-dialog' ); 397 share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ); 398 share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ); 399 share_input = document.querySelectorAll( '.wp-embed-share-input' ); 400 share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ); 401 402 if ( share_input ) { 403 for ( var i = 0; i < share_input.length; i++ ) { 404 share_input[ i ].addEventListener( 'click', function ( e ) { 405 e.target.select(); 406 } ); 407 } 408 } 409 410 function openSharingDialog() { 411 share_dialog.className = share_dialog.className.replace( 'hidden', '' ); 412 share_input[ 0 ].select(); 413 } 414 415 function closeSharingDialog() { 416 share_dialog.className += ' hidden'; 417 document.querySelector( '.wp-embed-share-dialog-open' ).focus(); 418 } 419 420 if ( share_dialog_open ) { 421 share_dialog_open.addEventListener( 'click', function ( e ) { 422 openSharingDialog(); 423 e.preventDefault(); 424 } ); 425 } 426 427 if ( share_dialog_close ) { 428 share_dialog_close.addEventListener( 'click', function ( e ) { 429 closeSharingDialog(); 430 e.preventDefault(); 431 } ); 432 } 433 434 if ( share_dialog_tabs ) { 435 for ( var i = 0; i < share_dialog_tabs.length; i++ ) { 436 share_dialog_tabs[ i ].addEventListener( 'click', function ( e ) { 437 var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); 438 currentTab.setAttribute( 'aria-selected', 'false' ); 439 document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 440 441 e.target.setAttribute( 'aria-selected', 'true' ); 442 document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 443 } ); 444 445 share_dialog_tabs[ i ].addEventListener( 'keydown', function ( e ) { 446 var previousSibling = e.target.parentElement.previousElementSibling, 447 nextSibling = e.target.parentElement.nextElementSibling, 448 newTab; 449 450 if ( 37 === e.keyCode ) { 451 newTab = previousSibling; 452 } else if ( 39 === e.keyCode ) { 453 newTab = nextSibling; 454 } else { 455 return false; 456 } 457 458 if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) { 459 newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling; 460 } 461 462 if ( newTab ) { 463 e.target.setAttribute( 'tabindex', '-1' ); 464 e.target.setAttribute( 'aria-selected', false ); 465 document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 466 467 newTab.firstElementChild.setAttribute( 'tabindex', '0' ); 468 newTab.firstElementChild.setAttribute( 'aria-selected', 'true' ); 469 newTab.firstElementChild.focus(); 470 document.querySelector( '#' + newTab.firstElementChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 471 } 472 } ); 473 } 474 } 475 476 document.addEventListener( 'keydown', function ( e ) { 477 if ( e.keyCode === 27 && -1 === share_dialog.className.indexOf( 'hidden' ) ) { 478 closeSharingDialog(); 479 } 480 }, false ); 481 482 if ( window.self === window.top ) { 483 return; 484 } 485 486 /** 487 * Send this document's height to the parent (embedding) site. 488 */ 489 sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); 490 491 /** 492 * Detect clicks to external (_top) links. 493 */ 494 var links = document.getElementsByTagName( 'a' ), href; 495 for ( var i = 0; i < links.length; i++ ) { 496 links[ i ].addEventListener( 'click', function ( e ) { 497 if ( e.target.hasAttribute( 'href' ) ) { 498 href = e.target.getAttribute( 'href' ); 499 } else { 500 href = e.target.parentElement.getAttribute( 'href' ); 501 } 502 503 /** 504 * Send link target to the parent (embedding) site. 505 */ 506 sendEmbedMessage( 'link', href ); 507 e.preventDefault(); 508 } ); 509 } 510 } 511 512 document.addEventListener( 'DOMContentLoaded', onLoad, false ); 513 514 /** 515 * Iframe resize handler. 516 */ 517 function onResize() { 518 if ( window.self === window.top ) { 519 return; 520 } 521 522 clearTimeout( resizing ); 523 524 resizing = setTimeout( function () { 525 sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); 526 }, 100 ); 527 } 528 529 window.addEventListener( 'resize', onResize, false ); 530 })( window, document ); 531 </script> 532 <?php 533 /** 534 * Print scripts or data in the embed template <head> tag. 535 * 536 * @since 4.4.0 537 */ 538 do_action( 'oembed_head' ); 539 ?> 540 </head> 541 <body <?php body_class(); ?>> 542 <?php 543 if ( have_posts() ) : 544 while ( have_posts() ) : the_post(); 545 // Add post thumbnail to response if available. 546 $thumbnail_id = false; 547 548 if ( has_post_thumbnail() ) { 549 $thumbnail_id = get_post_thumbnail_id(); 550 } 551 552 if ( 'attachment' === get_post_type() && wp_attachment_is_image() ) { 553 $thumbnail_id = get_the_ID(); 554 } 555 556 if ( $thumbnail_id ) { 557 $aspect_ratio = 1; 558 $measurements = array( 1, 1 ); 559 $image_size = 'full'; // Fallback. 560 561 $meta = wp_get_attachment_metadata( $thumbnail_id ); 562 if ( is_array( $meta ) ) { 563 foreach ( $meta['sizes'] as $size => $data ) { 564 if ( $data['width'] / $data['height'] > $aspect_ratio ) { 565 $aspect_ratio = $data['width'] / $data['height']; 566 $measurements = array( $data['width'], $data['height'] ); 567 $image_size = $size; 568 } 569 } 570 } 571 572 /** 573 * Filter the thumbnail image size for use in the embed template. 574 * 575 * @param string $image_size Thumbnail image size. 576 */ 577 $image_size = apply_filters( 'oembed_thumbnail_image_size', $image_size ); 578 579 $shape = $measurements[0] / $measurements[1] >= 1.75 ? 'rectangular' : 'square'; 580 581 /** 582 * Filter the thumbnail shape for use in the embed template. 583 * 584 * Rectangular images are shown above the title 585 * while square images are shown next to the content. 586 * 587 * @since 4.4.0 588 * 589 * @param string $shape Thumbnail image shape. Either 'rectangular' or 'square'. 590 */ 591 $shape = apply_filters( 'oembed_thumbnail_image_shape', $shape ); 592 } 593 ?> 594 <div <?php post_class( 'wp-embed' ); ?>> 595 <?php if ( $thumbnail_id && 'rectangular' === $shape ) : ?> 596 <div class="wp-embed-featured-image rectangular"> 597 <a href="<?php the_permalink(); ?>" target="_top"> 598 <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?> 599 </a> 600 </div> 601 <?php endif; ?> 602 603 <p class="wp-embed-heading"> 604 <a href="<?php the_permalink(); ?>" target="_top"> 605 <?php the_title(); ?> 606 </a> 607 </p> 608 609 <?php if ( $thumbnail_id && 'square' === $shape ) : ?> 610 <div class="wp-embed-featured-image square"> 611 <a href="<?php the_permalink(); ?>" target="_top"> 612 <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?> 613 </a> 614 </div> 615 <?php endif; ?> 616 617 <div class="wp-embed-excerpt"><?php the_excerpt_embed(); ?></div> 618 619 <?php 620 /** 621 * Print additional content after the embed excerpt. 622 * 623 * @since 4.4.0 624 */ 625 do_action( 'oembed_content' ); 626 ?> 627 628 <div class="wp-embed-footer"> 629 <div class="wp-embed-site-title"> 630 <?php 631 $site_icon_url = admin_url( 'images/w-logo-blue.png' ); 632 633 if ( function_exists( 'get_site_icon_url' ) ) { 634 $site_icon_url = get_site_icon_url( 32, $site_icon_url ); 635 } 636 637 /** 638 * Filters the site icon URL for use in the embed template. 639 * 640 * @param string $site_icon_url The site icon URL. 641 */ 642 $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url ); 643 644 printf( 645 '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>', 646 esc_url( home_url() ), 647 esc_url( $site_icon_url ), 648 esc_attr( get_bloginfo( 'name' ) ) 649 ); 650 ?> 651 </div> 652 653 <div class="wp-embed-meta"> 654 <?php 655 /** 656 * Print additional meta content in the embed template. 657 * 658 * @since 4.4.0 659 */ 660 do_action( 'oembed_content_meta') 661 ?> 662 <?php if ( get_comments_number() || comments_open() ) : ?> 663 <div class="wp-embed-comments"> 664 <a href="<?php comments_link(); ?>" target="_top"> 665 <span class="dashicons dashicons-admin-comments"></span> 666 <?php 667 printf( 668 _n( 669 '%s <span class="screen-reader-text">Comment</span>', 670 '%s <span class="screen-reader-text">Comments</span>', 671 get_comments_number(), 672 'oembed-api' 673 ), 674 absint( get_comments_number() ) 675 ); 676 ?> 677 </a> 678 </div> 679 <?php endif; ?> 680 <div class="wp-embed-share"> 681 <button type="button" class="wp-embed-share-dialog-open" 682 aria-label="<?php esc_attr_e( 'Open sharing dialog', 'oembed-api' ); ?>"> 683 <span class="dashicons dashicons-share"></span> 684 </button> 685 </div> 686 </div> 687 </div> 688 <div class="wp-embed-share-dialog hidden"> 689 <div class="wp-embed-share-dialog-content"> 690 <div class="wp-embed-share-dialog-text"> 691 <ul class="wp-embed-share-tabs" role="tablist"> 692 <li id="wp-embed-share-tab-button-wordpress" class="wp-embed-share-tab-button" role="presentation"> 693 <button role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed', 'oembed-api' ); ?></button> 694 </li> 695 <li id="wp-embed-share-tab-button-embed" class="wp-embed-share-tab-button" role="presentation"> 696 <button role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed', 'oembed-api' ); ?></button> 697 </li> 698 </ul> 699 <div id="wp-embed-share-tab-wordpress" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-wordpress" aria-hidden="false"> 700 <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" tabindex="0" readonly/> 701 702 <p class="wp-embed-share-description"> 703 <?php _e( 'Copy and paste this URL into your WordPress site to embed', 'oembed-api' ); ?> 704 </p> 705 </div> 706 <div id="wp-embed-share-tab-html" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-html" aria-hidden="true"> 707 <textarea class="wp-embed-share-input" tabindex="0" readonly><?php echo esc_attr( get_post_embed_html( null, 600, 400 ) ); ?></textarea> 708 709 <p class="wp-embed-share-description"> 710 <?php _e( 'Copy and paste this code into your site to embed', 'oembed-api' ); ?> 711 </p> 712 </div> 713 </div> 714 715 <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog', 'oembed-api' ); ?>"> 716 <span class="dashicons dashicons-no"></span> 717 </button> 718 </div> 719 </div> 720 </div> 721 <?php 722 endwhile; 723 else : 724 ?> 725 <div class="wp-embed"> 726 <p class="wp-embed-heading"><?php _e( 'Page not found', 'oembed-api' ); ?></p> 727 728 <div class="wp-embed-excerpt"> 729 <p><?php _e( 'Error 404! The requested content was not found.', 'oembed-api' ) ?></p> 730 </div> 731 732 <div class="wp-embed-footer"> 733 <div class="wp-embed-site-title"> 734 <?php 735 $site_icon_url = admin_url( 'images/w-logo-blue.png' ); 736 737 if ( function_exists( 'get_site_icon_url' ) ) { 738 $site_icon_url = get_site_icon_url( 32, $site_icon_url ); 739 } 740 741 /** 742 * Filters the site icon URL for use in the embed template. 743 * 744 * @param string $site_icon_url The site icon URL. 745 */ 746 $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url ); 747 748 printf( 749 '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>', 750 esc_url( home_url() ), 751 esc_url( $site_icon_url ), 752 esc_attr( get_bloginfo( 'name' ) ) 753 ); 754 ?> 755 </div> 756 </div> 757 </div> 758 <?php 759 endif; 760 761 /** 762 * Print scripts or data before the closing body tag in the embed template. 763 * 764 * @since 4.4.0 765 */ 766 do_action( 'oembed_footer' ); 767 ?> 768 </body> 769 </html> -
new file src/wp-includes/js/tinymce/plugins/wpoembed/plugin.js
diff --git src/wp-includes/js/tinymce/plugins/wpoembed/plugin.js src/wp-includes/js/tinymce/plugins/wpoembed/plugin.js new file mode 100644 index 0000000..3572426
- + 1 (function ( tinymce ) { 2 'use strict'; 3 4 tinymce.PluginManager.add( 'wpoembed', function ( editor, url ) { 5 editor.on( 'init', function () { 6 var scriptId = editor.dom.uniqueId(); 7 8 var scriptElm = editor.dom.create( 'script', { 9 id: scriptId, 10 type: 'text/javascript', 11 src: url + '/../../../wp-oembed.js' 12 } ); 13 14 editor.getDoc().getElementsByTagName( 'head' )[ 0 ].appendChild( scriptElm ); 15 } ); 16 } ); 17 })( window.tinymce ); -
new file src/wp-includes/js/wp-oembed.js
diff --git src/wp-includes/js/wp-oembed.js src/wp-includes/js/wp-oembed.js new file mode 100644 index 0000000..0715905
- + 1 (function ( window, document ) { 2 'use strict'; 3 4 window.wp = window.wp || {}; 5 6 if ( !! window.wp.receiveEmbedMessage ) { 7 return; 8 } 9 10 window.wp.receiveEmbedMessage = function( e ) { 11 if ( ! ( e.data.secret || e.data.message || e.data.value ) ) { 12 return; 13 } 14 15 var iframes = document.querySelectorAll( '.wp-embedded-content[data-secret="' + e.data.secret + '"]' ); 16 17 for ( var i = 0; i < iframes.length; i++ ) { 18 var source = iframes[ i ]; 19 20 /* Resize the iframe on request. */ 21 if ( 'height' === e.data.message ) { 22 var height = e.data.value; 23 if ( height > 1000 ) { 24 height = 1000; 25 } else if ( height < 200 ) { 26 height = 200; 27 } 28 29 source.height = (height) + "px"; 30 } 31 32 /* Link to a specific URL on request. */ 33 if ( 'link' === e.data.message ) { 34 var sourceURL = document.createElement( 'a' ), targetURL = document.createElement( 'a' ); 35 sourceURL.href = source.getAttribute( 'src' ); 36 targetURL.href = e.data.value; 37 38 /* Only continue if link hostname matches iframe's hostname. */ 39 if ( targetURL.host === sourceURL.host && document.activeElement === source ) { 40 window.top.location.href = e.data.value; 41 } 42 } 43 } 44 } 45 46 window.addEventListener( 'message', window.wp.receiveEmbedMessage, false ); 47 48 function onLoad() { 49 var isIE10 = 10 === new Function( "/*@cc_on return @_jscript_version; @*/" )(), 50 isIE11 = !!navigator.userAgent.match( /Trident.*rv\:11\./ ); 51 52 /* Remove security attribute from iframes in IE10 and IE11. */ 53 if ( isIE10 || isIE11 ) { 54 var iframes = document.querySelectorAll( '.wp-embedded-content[security]' ), iframeClone; 55 56 for ( var i = 0; i < iframes.length; i++ ) { 57 iframeClone = iframes[ i ].cloneNode( true ); 58 iframeClone.removeAttribute( 'security' ); 59 iframes[ i ].parentNode.insertBefore( iframeClone, iframes[ i ].nextSibling ); 60 iframes[ i ].parentNode.removeChild( iframes[ i ] ); 61 } 62 } 63 } 64 65 document.addEventListener( 'DOMContentLoaded', onLoad, false ); 66 })( window, document ); -
src/wp-includes/media.php
diff --git src/wp-includes/media.php src/wp-includes/media.php index 44e18f4..53503e9 100644
function wp_imagecreatetruecolor($width, $height) { 2177 2177 } 2178 2178 2179 2179 /** 2180 * Registers an embed handler.2181 *2182 * Should probably only be used for sites that do not support oEmbed.2183 *2184 * @since 2.9.02185 *2186 * @global WP_Embed $wp_embed2187 *2188 * @param string $id An internal ID/name for the handler. Needs to be unique.2189 * @param string $regex The regex that will be used to see if this handler should be used for a URL.2190 * @param callable $callback The callback function that will be called if the regex is matched.2191 * @param int $priority Optional. Used to specify the order in which the registered handlers will2192 * be tested. Default 10.2193 */2194 function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {2195 global $wp_embed;2196 $wp_embed->register_handler( $id, $regex, $callback, $priority );2197 }2198 2199 /**2200 * Unregisters a previously-registered embed handler.2201 *2202 * @since 2.9.02203 *2204 * @global WP_Embed $wp_embed2205 *2206 * @param string $id The handler ID that should be removed.2207 * @param int $priority Optional. The priority of the handler to be removed. Default 10.2208 */2209 function wp_embed_unregister_handler( $id, $priority = 10 ) {2210 global $wp_embed;2211 $wp_embed->unregister_handler( $id, $priority );2212 }2213 2214 /**2215 * Create default array of embed parameters.2216 *2217 * The width defaults to the content width as specified by the theme. If the2218 * theme does not specify a content width, then 500px is used.2219 *2220 * The default height is 1.5 times the width, or 1000px, whichever is smaller.2221 *2222 * The 'embed_defaults' filter can be used to adjust either of these values.2223 *2224 * @since 2.9.02225 *2226 * @global int $content_width2227 *2228 * @param string $url Optional. The URL that should be embedded. Default empty.2229 *2230 * @return array Default embed parameters.2231 */2232 function wp_embed_defaults( $url = '' ) {2233 if ( ! empty( $GLOBALS['content_width'] ) )2234 $width = (int) $GLOBALS['content_width'];2235 2236 if ( empty( $width ) )2237 $width = 500;2238 2239 $height = min( ceil( $width * 1.5 ), 1000 );2240 2241 /**2242 * Filter the default array of embed dimensions.2243 *2244 * @since 2.9.02245 *2246 * @param int $width Width of the embed in pixels.2247 * @param int $height Height of the embed in pixels.2248 * @param string $url The URL that should be embedded.2249 */2250 return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url );2251 }2252 2253 /**2254 2180 * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height. 2255 2181 * 2256 2182 * @since 2.9.0 … … function wp_expand_dimensions( $example_width, $example_height, $max_width, $max 2273 2199 } 2274 2200 2275 2201 /** 2276 * Attempts to fetch the embed HTML for a provided URL using oEmbed.2277 *2278 * @since 2.9.02279 *2280 * @see WP_oEmbed2281 *2282 * @param string $url The URL that should be embedded.2283 * @param array $args Optional. Additional arguments and parameters for retrieving embed HTML.2284 * Default empty.2285 * @return false|string False on failure or the embed HTML on success.2286 */2287 function wp_oembed_get( $url, $args = '' ) {2288 require_once( ABSPATH . WPINC . '/class-oembed.php' );2289 $oembed = _wp_oembed_get_object();2290 return $oembed->get_html( $url, $args );2291 }2292 2293 /**2294 * Adds a URL format and oEmbed provider URL pair.2295 *2296 * @since 2.9.02297 *2298 * @see WP_oEmbed2299 *2300 * @param string $format The format of URL that this provider can handle. You can use asterisks2301 * as wildcards.2302 * @param string $provider The URL to the oEmbed provider.2303 * @param boolean $regex Optional. Whether the `$format` parameter is in a RegEx format. Default false.2304 */2305 function wp_oembed_add_provider( $format, $provider, $regex = false ) {2306 require_once( ABSPATH . WPINC . '/class-oembed.php' );2307 2308 if ( did_action( 'plugins_loaded' ) ) {2309 $oembed = _wp_oembed_get_object();2310 $oembed->providers[$format] = array( $provider, $regex );2311 } else {2312 WP_oEmbed::_add_provider_early( $format, $provider, $regex );2313 }2314 }2315 2316 /**2317 * Removes an oEmbed provider.2318 *2319 * @since 3.5.02320 *2321 * @see WP_oEmbed2322 *2323 * @param string $format The URL format for the oEmbed provider to remove.2324 * @return bool Was the provider removed successfully?2325 */2326 function wp_oembed_remove_provider( $format ) {2327 require_once( ABSPATH . WPINC . '/class-oembed.php' );2328 2329 if ( did_action( 'plugins_loaded' ) ) {2330 $oembed = _wp_oembed_get_object();2331 2332 if ( isset( $oembed->providers[ $format ] ) ) {2333 unset( $oembed->providers[ $format ] );2334 return true;2335 }2336 } else {2337 WP_oEmbed::_remove_provider_early( $format );2338 }2339 2340 return false;2341 }2342 2343 /**2344 * Determines if default embed handlers should be loaded.2345 *2346 * Checks to make sure that the embeds library hasn't already been loaded. If2347 * it hasn't, then it will load the embeds library.2348 *2349 * @since 2.9.02350 *2351 * @see wp_embed_register_handler()2352 */2353 function wp_maybe_load_embeds() {2354 /**2355 * Filter whether to load the default embed handlers.2356 *2357 * Returning a falsey value will prevent loading the default embed handlers.2358 *2359 * @since 2.9.02360 *2361 * @param bool $maybe_load_embeds Whether to load the embeds library. Default true.2362 */2363 if ( ! apply_filters( 'load_default_embeds', true ) ) {2364 return;2365 }2366 2367 wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/(?:v|embed)/([^/]+)#i', 'wp_embed_handler_youtube' );2368 2369 wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );2370 2371 /**2372 * Filter the audio embed handler callback.2373 *2374 * @since 3.6.02375 *2376 * @param callable $handler Audio embed handler callback function.2377 */2378 wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 );2379 2380 /**2381 * Filter the video embed handler callback.2382 *2383 * @since 3.6.02384 *2385 * @param callable $handler Video embed handler callback function.2386 */2387 wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 );2388 }2389 2390 /**2391 * The Google Video embed handler callback.2392 *2393 * Google Video does not support oEmbed.2394 *2395 * @see WP_Embed::register_handler()2396 * @see WP_Embed::shortcode()2397 *2398 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().2399 * @param array $attr Embed attributes.2400 * @param string $url The original URL that was matched by the regex.2401 * @param array $rawattr The original unmodified attributes.2402 * @return string The embed HTML.2403 */2404 function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {2405 // If the user supplied a fixed width AND height, use it2406 if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {2407 $width = (int) $rawattr['width'];2408 $height = (int) $rawattr['height'];2409 } else {2410 list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );2411 }2412 2413 /**2414 * Filter the Google Video embed output.2415 *2416 * @since 2.9.02417 *2418 * @param string $html Google Video HTML embed markup.2419 * @param array $matches The RegEx matches from the provided regex.2420 * @param array $attr An array of embed attributes.2421 * @param string $url The original URL that was matched by the regex.2422 * @param array $rawattr The original unmodified attributes.2423 */2424 return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&hl=en&fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr );2425 }2426 2427 /**2428 * YouTube iframe embed handler callback.2429 *2430 * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is.2431 *2432 * @since 4.0.02433 *2434 * @global WP_Embed $wp_embed2435 *2436 * @param array $matches The RegEx matches from the provided regex when calling2437 * wp_embed_register_handler().2438 * @param array $attr Embed attributes.2439 * @param string $url The original URL that was matched by the regex.2440 * @param array $rawattr The original unmodified attributes.2441 * @return string The embed HTML.2442 */2443 function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) {2444 global $wp_embed;2445 $embed = $wp_embed->autoembed( "https://youtube.com/watch?v={$matches[2]}" );2446 2447 /**2448 * Filter the YoutTube embed output.2449 *2450 * @since 4.0.02451 *2452 * @see wp_embed_handler_youtube()2453 *2454 * @param string $embed YouTube embed output.2455 * @param array $attr An array of embed attributes.2456 * @param string $url The original URL that was matched by the regex.2457 * @param array $rawattr The original unmodified attributes.2458 */2459 return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr );2460 }2461 2462 /**2463 * Audio embed handler callback.2464 *2465 * @since 3.6.02466 *2467 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().2468 * @param array $attr Embed attributes.2469 * @param string $url The original URL that was matched by the regex.2470 * @param array $rawattr The original unmodified attributes.2471 * @return string The embed HTML.2472 */2473 function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) {2474 $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) );2475 2476 /**2477 * Filter the audio embed output.2478 *2479 * @since 3.6.02480 *2481 * @param string $audio Audio embed output.2482 * @param array $attr An array of embed attributes.2483 * @param string $url The original URL that was matched by the regex.2484 * @param array $rawattr The original unmodified attributes.2485 */2486 return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr );2487 }2488 2489 /**2490 * Video embed handler callback.2491 *2492 * @since 3.6.02493 *2494 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().2495 * @param array $attr Embed attributes.2496 * @param string $url The original URL that was matched by the regex.2497 * @param array $rawattr The original unmodified attributes.2498 * @return string The embed HTML.2499 */2500 function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {2501 $dimensions = '';2502 if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {2503 $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );2504 $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );2505 }2506 $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) );2507 2508 /**2509 * Filter the video embed output.2510 *2511 * @since 3.6.02512 *2513 * @param string $video Video embed output.2514 * @param array $attr An array of embed attributes.2515 * @param string $url The original URL that was matched by the regex.2516 * @param array $rawattr The original unmodified attributes.2517 */2518 return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );2519 }2520 2521 /**2522 2202 * Converts a shorthand byte value to an integer byte value. 2523 2203 * 2524 2204 * @since 2.3.0 -
new file src/wp-includes/oembed-functions.php
diff --git src/wp-includes/oembed-functions.php src/wp-includes/oembed-functions.php new file mode 100644 index 0000000..9630b23
- + 1 <?php 2 /** 3 * WordPress API for embedding content. 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 * Create 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 '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 * 61 * @return array Default embed parameters. 62 */ 63 function wp_embed_defaults( $url = '' ) { 64 if ( ! empty( $GLOBALS['content_width'] ) ) 65 $width = (int) $GLOBALS['content_width']; 66 67 if ( empty( $width ) ) 68 $width = 500; 69 70 $height = min( ceil( $width * 1.5 ), 1000 ); 71 72 /** 73 * Filter the default array of embed dimensions. 74 * 75 * @since 2.9.0 76 * 77 * @param int $width Width of the embed in pixels. 78 * @param int $height Height of the embed in pixels. 79 * @param string $url The URL that should be embedded. 80 */ 81 return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url ); 82 } 83 84 /** 85 * Attempts to fetch the embed HTML for a provided URL using oEmbed. 86 * 87 * @since 2.9.0 88 * 89 * @see WP_oEmbed 90 * 91 * @param string $url The URL that should be embedded. 92 * @param array $args Optional. Additional arguments and parameters for retrieving embed HTML. 93 * Default empty. 94 * @return false|string False on failure or the embed HTML on success. 95 */ 96 function wp_oembed_get( $url, $args = '' ) { 97 require_once( ABSPATH . WPINC . '/class-oembed.php' ); 98 $oembed = _wp_oembed_get_object(); 99 return $oembed->get_html( $url, $args ); 100 } 101 102 /** 103 * Adds a URL format and oEmbed provider URL pair. 104 * 105 * @since 2.9.0 106 * 107 * @see WP_oEmbed 108 * 109 * @param string $format The format of URL that this provider can handle. You can use asterisks 110 * as wildcards. 111 * @param string $provider The URL to the oEmbed provider. 112 * @param boolean $regex Optional. Whether the `$format` parameter is in a RegEx format. Default false. 113 */ 114 function wp_oembed_add_provider( $format, $provider, $regex = false ) { 115 require_once( ABSPATH . WPINC . '/class-oembed.php' ); 116 117 if ( did_action( 'plugins_loaded' ) ) { 118 $oembed = _wp_oembed_get_object(); 119 $oembed->providers[$format] = array( $provider, $regex ); 120 } else { 121 WP_oEmbed::_add_provider_early( $format, $provider, $regex ); 122 } 123 } 124 125 /** 126 * Removes an oEmbed provider. 127 * 128 * @since 3.5.0 129 * 130 * @see WP_oEmbed 131 * 132 * @param string $format The URL format for the oEmbed provider to remove. 133 * @return bool Was the provider removed successfully? 134 */ 135 function wp_oembed_remove_provider( $format ) { 136 require_once( ABSPATH . WPINC . '/class-oembed.php' ); 137 138 if ( did_action( 'plugins_loaded' ) ) { 139 $oembed = _wp_oembed_get_object(); 140 141 if ( isset( $oembed->providers[ $format ] ) ) { 142 unset( $oembed->providers[ $format ] ); 143 return true; 144 } 145 } else { 146 WP_oEmbed::_remove_provider_early( $format ); 147 } 148 149 return false; 150 } 151 152 /** 153 * Determines if default embed handlers should be loaded. 154 * 155 * Checks to make sure that the embeds library hasn't already been loaded. If 156 * it hasn't, then it will load the embeds library. 157 * 158 * @since 2.9.0 159 * 160 * @see wp_embed_register_handler() 161 */ 162 function wp_maybe_load_embeds() { 163 /** 164 * Filter whether to load the default embed handlers. 165 * 166 * Returning a falsey value will prevent loading the default embed handlers. 167 * 168 * @since 2.9.0 169 * 170 * @param bool $maybe_load_embeds Whether to load the embeds library. Default true. 171 */ 172 if ( ! apply_filters( 'load_default_embeds', true ) ) { 173 return; 174 } 175 176 wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/(?:v|embed)/([^/]+)#i', 'wp_embed_handler_youtube' ); 177 178 wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' ); 179 180 /** 181 * Filter the audio embed handler callback. 182 * 183 * @since 3.6.0 184 * 185 * @param callable $handler Audio embed handler callback function. 186 */ 187 wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 ); 188 189 /** 190 * Filter the video embed handler callback. 191 * 192 * @since 3.6.0 193 * 194 * @param callable $handler Video embed handler callback function. 195 */ 196 wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 ); 197 } 198 199 /** 200 * The Google Video embed handler callback. 201 * 202 * Google Video does not support oEmbed. 203 * 204 * @see WP_Embed::register_handler() 205 * @see WP_Embed::shortcode() 206 * 207 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). 208 * @param array $attr Embed attributes. 209 * @param string $url The original URL that was matched by the regex. 210 * @param array $rawattr The original unmodified attributes. 211 * @return string The embed HTML. 212 */ 213 function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) { 214 // If the user supplied a fixed width AND height, use it 215 if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) { 216 $width = (int) $rawattr['width']; 217 $height = (int) $rawattr['height']; 218 } else { 219 list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] ); 220 } 221 222 /** 223 * Filter the Google Video embed output. 224 * 225 * @since 2.9.0 226 * 227 * @param string $html Google Video HTML embed markup. 228 * @param array $matches The RegEx matches from the provided regex. 229 * @param array $attr An array of embed attributes. 230 * @param string $url The original URL that was matched by the regex. 231 * @param array $rawattr The original unmodified attributes. 232 */ 233 return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&hl=en&fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr ); 234 } 235 236 /** 237 * YouTube iframe embed handler callback. 238 * 239 * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is. 240 * 241 * @since 4.0.0 242 * 243 * @global WP_Embed $wp_embed 244 * 245 * @param array $matches The RegEx matches from the provided regex when calling 246 * wp_embed_register_handler(). 247 * @param array $attr Embed attributes. 248 * @param string $url The original URL that was matched by the regex. 249 * @param array $rawattr The original unmodified attributes. 250 * @return string The embed HTML. 251 */ 252 function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) { 253 global $wp_embed; 254 $embed = $wp_embed->autoembed( "https://youtube.com/watch?v={$matches[2]}" ); 255 256 /** 257 * Filter the YoutTube embed output. 258 * 259 * @since 4.0.0 260 * 261 * @see wp_embed_handler_youtube() 262 * 263 * @param string $embed YouTube embed output. 264 * @param array $attr An array of embed attributes. 265 * @param string $url The original URL that was matched by the regex. 266 * @param array $rawattr The original unmodified attributes. 267 */ 268 return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr ); 269 } 270 271 /** 272 * Audio embed handler callback. 273 * 274 * @since 3.6.0 275 * 276 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). 277 * @param array $attr Embed attributes. 278 * @param string $url The original URL that was matched by the regex. 279 * @param array $rawattr The original unmodified attributes. 280 * @return string The embed HTML. 281 */ 282 function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) { 283 $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) ); 284 285 /** 286 * Filter the audio embed output. 287 * 288 * @since 3.6.0 289 * 290 * @param string $audio Audio embed output. 291 * @param array $attr An array of embed attributes. 292 * @param string $url The original URL that was matched by the regex. 293 * @param array $rawattr The original unmodified attributes. 294 */ 295 return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr ); 296 } 297 298 /** 299 * Video embed handler callback. 300 * 301 * @since 3.6.0 302 * 303 * @param array $matches The RegEx matches from the provided regex when calling wp_embed_register_handler(). 304 * @param array $attr Embed attributes. 305 * @param string $url The original URL that was matched by the regex. 306 * @param array $rawattr The original unmodified attributes. 307 * @return string The embed HTML. 308 */ 309 function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) { 310 $dimensions = ''; 311 if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) { 312 $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] ); 313 $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] ); 314 } 315 $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) ); 316 317 /** 318 * Filter the video embed output. 319 * 320 * @since 3.6.0 321 * 322 * @param string $video Video embed output. 323 * @param array $attr An array of embed attributes. 324 * @param string $url The original URL that was matched by the regex. 325 * @param array $rawattr The original unmodified attributes. 326 */ 327 return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr ); 328 } 329 330 /** 331 * Parse an oEmbed API query. 332 * 333 * @since 4.4.0 334 */ 335 function wp_oembed_parse_query( $wp_query ) { 336 $controller = new WP_oEmbed_Controller; 337 $controller->parse_query( $wp_query ); 338 } 339 340 /** 341 * Adds oEmbed discovery links in the website <head>. 342 * 343 * @since 4.4.0 344 */ 345 function wp_oembed_add_discovery_links() { 346 $output = ''; 347 348 if ( is_singular() ) { 349 $output .= '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n"; 350 $output .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n"; 351 } 352 353 /** 354 * Filter the oEmbed discovery links. 355 * 356 * @since 4.4.0 357 * 358 * @param string $output HTML of the discovery links. 359 */ 360 echo apply_filters( 'oembed_discovery_links', $output ); 361 } 362 363 /** 364 * Add the necessary JavaScript to communicate with the embedded iframes. 365 * 366 * @since 4.4.0 367 */ 368 function wp_oembed_add_host_js() { 369 wp_enqueue_script( 'wp-oembed' ); 370 } 371 372 373 /** 374 * Get the URL to embed a specific post in an iframe. 375 * 376 * @since 4.4.0 377 * 378 * @param int|WP_Post $post Optional. Post ID or object. Defaults to the current post. 379 * @return string|false The post embed URL on success, false if the post doesn't exist. 380 */ 381 function get_post_embed_url( $post = null ) { 382 $post = get_post( $post ); 383 384 if ( ! $post ) { 385 return false; 386 } 387 388 if ( get_option( 'permalink_structure' ) ) { 389 $embed_url = trailingslashit( get_permalink( $post ) ) . user_trailingslashit( 'embed' ); 390 } else { 391 $embed_url = add_query_arg( array( 'embed' => 'true' ), get_permalink( $post ) ); 392 } 393 394 /** 395 * Filter the URL to embed a specific post. 396 * 397 * @since 4.4.0 398 * 399 * @param string $embed_url The post embed URL. 400 * @param WP_Post $post The corresponding post object. 401 */ 402 return esc_url_raw( apply_filters( 'post_embed_url', $embed_url, $post ) ); 403 } 404 405 /** 406 * Get the oEmbed endpoint URL for a given permalink. 407 * 408 * Pass an empty string as the first argument 409 * to get the endpoint base URL. 410 * 411 * @since 4.4.0 412 * 413 * @param string $permalink Optional. The permalink used for the `url` query arg. Default empty. 414 * @param string $format Optional. The requested response format. Default 'json'. 415 * @return string The oEmbed endpoint URL. 416 */ 417 function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) { 418 $url = add_query_arg( array( 'oembed' => 'true' ), home_url( '/' ) ); 419 420 if ( 'json' === $format ) { 421 $format = false; 422 } 423 424 if ( '' !== $permalink ) { 425 $url = add_query_arg( array( 426 'url' => $permalink, 427 'format' => $format, 428 ), $url ); 429 } 430 431 /** 432 * Filter the oEmbed endpoint URL. 433 * 434 * @since 4.4.0 435 * 436 * @param string $url The URL to the oEmbed endpoint. 437 * @param string $permalink The permalink used for the `url` query arg. 438 * @param string $format The requested response format. 439 */ 440 return apply_filters( 'oembed_endpoint_url', $url, $permalink, $format ); 441 } 442 443 /** 444 * Get the embed code for a specific post. 445 * 446 * @since 4.4.0 447 * 448 * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`. 449 * @param int $width The width for the response. 450 * @param int $height The height for the response. 451 * @return string|false Embed code on success, false if post doesn't exist. 452 */ 453 function get_post_embed_html( $post = null, $width, $height ) { 454 $post = get_post( $post ); 455 456 if ( ! $post ) { 457 return false; 458 } 459 460 $embed_url = get_post_embed_url( $post ); 461 462 $output = "<script type='text/javascript'>\n"; 463 $output .= file_get_contents( ABSPATH . WPINC . '/js/wp-oembed.js' ); 464 $output .= "\n</script>"; 465 466 $output .= sprintf( 467 '<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>', 468 esc_url( $embed_url ), 469 absint( $width ), 470 absint( $height ), 471 esc_attr__( 'Embedded WordPress Post', 'oembed-api' ) 472 ); 473 474 /** 475 * Filters the oEmbed HTML output. 476 * 477 * @since 4.4.0 478 * 479 * @param string $output The default HTML. 480 * @param WP_Post $post Current post object. 481 * @param int $width Width of the response. 482 * @param int $height Height of the response. 483 */ 484 return apply_filters( 'oembed_html', $output, $post, $width, $height ); 485 } 486 487 /** 488 * Get the oEmbed response data for a given post. 489 * 490 * @since 4.4.0 491 * 492 * @param WP_Post|int $post Optional. Post object or ID. Default is global `$post`. 493 * @param int $width The requested width. 494 * @return array|false Response data on success, false if post doesn't exist. 495 */ 496 function get_oembed_response_data( $post = null, $width ) { 497 $post = get_post( $post ); 498 499 if ( ! $post ) { 500 return false; 501 } 502 503 if ( 'publish' !== get_post_status( $post ) ) { 504 return false; 505 } 506 507 /** 508 * Filter the allowed minimum width for the oEmbed response. 509 * 510 * @param int $width The minimum width. Defaults to 200. 511 */ 512 $minwidth = apply_filters( 'oembed_minwidth', 200 ); 513 514 /** 515 * Filter the allowed maximum width for the oEmbed response. 516 * 517 * @param int $width The maximum width. Defaults to 600. 518 */ 519 $maxwidth = apply_filters( 'oembed_maxwidth', 600 ); 520 521 if ( $width < $minwidth ) { 522 $width = $minwidth; 523 } else if ( $width > $maxwidth ) { 524 $width = $maxwidth; 525 } 526 527 $height = ceil( $width / 16 * 9 ); 528 529 if ( 200 > $height ) { 530 $height = 200; 531 } 532 533 $data = array( 534 'version' => '1.0', 535 'provider_name' => get_bloginfo( 'name' ), 536 'provider_url' => get_home_url(), 537 'author_name' => get_bloginfo( 'name' ), 538 'author_url' => get_home_url(), 539 'title' => $post->post_title, 540 'type' => 'link', 541 ); 542 543 $author = get_userdata( $post->post_author ); 544 545 if ( $author ) { 546 $data['author_name'] = $author->display_name; 547 $data['author_url'] = get_author_posts_url( $author->ID ); 548 } 549 550 /** 551 * Filter the oEmbed response data. 552 * 553 * @since 4.4.0 554 * 555 * @param array $data The response data. 556 * @param WP_Post $post The post object. 557 * @param int $width The requested width. 558 * @param int $height The calculated height. 559 */ 560 return apply_filters( 'oembed_response_data', $data, $post, $width, $height ); 561 } 562 563 /** 564 * Filters the oEmbed response data to return an iframe embed code. 565 * 566 * @since 4.4.0 567 * 568 * @param array $data The response data. 569 * @param WP_Post $post The post object. 570 * @param int $width The requested width. 571 * @param int $height The calculated height. 572 * @return array The modified response data. 573 */ 574 function get_oembed_response_data_rich( $data, $post, $width, $height ) { 575 $data['width'] = absint( $width ); 576 $data['height'] = absint( $height ); 577 $data['type'] = 'rich'; 578 $data['html'] = get_post_embed_html( $post, $width, $height ); 579 580 // Add post thumbnail to response if available. 581 $thumbnail_id = false; 582 583 if ( has_post_thumbnail( $post->ID ) ) { 584 $thumbnail_id = get_post_thumbnail_id( $post->ID ); 585 } 586 587 if ( 'attachment' === get_post_type( $post ) ) { 588 if ( wp_attachment_is_image( $post ) ) { 589 $thumbnail_id = $post->ID; 590 } else if ( wp_attachment_is( 'video', $post ) ) { 591 $thumbnail_id = get_post_thumbnail_id( $post ); 592 $data['type'] = 'video'; 593 } 594 } 595 596 if ( $thumbnail_id ) { 597 list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) ); 598 $data['thumbnail_url'] = $thumbnail_url; 599 $data['thumbnail_width'] = $thumbnail_width; 600 $data['thumbnail_height'] = $thumbnail_height; 601 } 602 603 return $data; 604 } 605 606 /** 607 * Ensures that the specified format is either 'json' or 'xml'. 608 * 609 * @since 4.4.0 610 * 611 * @param string $format The oEmbed response format. Accepts 'json', 'xml'. 612 * @return string The format, either 'xml' or 'json'. Default 'json'. 613 */ 614 function wp_oembed_ensure_format( $format ) { 615 if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) { 616 return 'json'; 617 } 618 619 return $format; 620 } 621 622 /** 623 * Creates an XML string from a given array. 624 * 625 * @since 4.4.0 626 * @access private 627 * 628 * @param array $data The original oEmbed response data. 629 * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. 630 * @return string|false XML string on success, false on error. 631 */ 632 function _oembed_create_xml( $data, $node = null ) { 633 if ( ! is_array( $data ) || empty( $data ) ) { 634 return false; 635 } 636 637 if ( null === $node ) { 638 $node = new SimpleXMLElement( '<oembed></oembed>' ); 639 } 640 641 foreach ( $data as $key => $value ) { 642 if ( is_numeric( $key ) ) { 643 $key = 'oembed'; 644 } 645 646 if ( is_array( $value ) ) { 647 $item = $node->addChild( $key ); 648 _oembed_create_xml( $value, $item ); 649 } else { 650 $node->addChild( $key, esc_html( $value ) ); 651 } 652 } 653 654 return $node->asXML(); 655 } 656 657 /** 658 * Filters the returned oEmbed HTML. 659 * 660 * If the $url isn't on the trusted providers list, 661 * we need to filter the HTML heavily for security. 662 * 663 * Only filters 'rich' and 'html' response types. 664 * 665 * @since 4.4.0 666 * 667 * @param string $return The returned oEmbed HTML. 668 * @param object $data A data object result from an oEmbed provider. 669 * @param string $url The URL of the content to be embedded. 670 * @return string The filtered and sanitized oEmbed result. 671 */ 672 function wp_filter_oembed_result( $return, $data, $url ) { 673 if ( false === $return || ! in_array( $data->type, array( 'rich', 'video' ) ) ) { 674 return $return; 675 } 676 677 require_once( ABSPATH . WPINC . '/class-oembed.php' ); 678 $wp_oembed = _wp_oembed_get_object(); 679 680 // Don't modify the HTML for trusted providers. 681 if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) { 682 return $return; 683 } 684 685 $allowed_html = array( 686 'iframe' => array( 687 'src' => true, 688 'width' => true, 689 'height' => true, 690 'frameborder' => true, 691 'marginwidth' => true, 692 'marginheight' => true, 693 'scrolling' => true, 694 'title' => true, 695 'class' => true, 696 ), 697 ); 698 699 $html = wp_kses( $return, $allowed_html ); 700 preg_match( '|^.*(<iframe.*?></iframe>).*$|m', $html, $iframes ); 701 702 if ( empty( $iframes ) ) { 703 return false; 704 } 705 706 $html = str_replace( '<iframe', '<iframe sandbox="allow-scripts" security="restricted"', $iframes[1] ); 707 708 preg_match( '/ src=[\'"]([^\'"]*)[\'"]/', $html, $results ); 709 710 if ( ! empty( $results ) ) { 711 $secret = wp_generate_password( 10, false ); 712 713 $url = esc_url( "{$results[1]}#?secret=$secret" ); 714 715 $html = str_replace( $results[0], " src=\"$url\" data-secret=\"$secret\"", $html ); 716 } 717 718 return $html; 719 } 720 721 /** 722 * Filters the string in the "more" link displayed after a trimmed excerpt. 723 * 724 * @since 4.4.0 725 * 726 * @param string $more_string The string shown within the more link. 727 * @return string The modified excerpt. 728 */ 729 function wp_oembed_excerpt_more( $more_string ) { 730 if ( ! is_embed() ) { 731 return $more_string; 732 } 733 734 return sprintf( 735 _x( '… %s', 'read more link', 'oembed-api' ), 736 sprintf( 737 '<a class="wp-embed-more" href="%s" target="_top">%s</a>', 738 get_the_permalink(), 739 __( 'Read more', 'oembed-api' ) 740 ) 741 ); 742 } 743 744 /** 745 * Display the post excerpt for the embed template. 746 * 747 * @since 4.4.0 748 */ 749 function the_excerpt_embed() { 750 $output = get_the_excerpt(); 751 752 /** 753 * Filter the post excerpt for the embed template. 754 * 755 * @param string $output The current post excerpt. 756 */ 757 echo apply_filters( 'the_excerpt_embed', $output ); 758 } 759 760 /** 761 * Filters the post excerpt for the embed template. 762 * 763 * Shows players for video and audio attachments. 764 * 765 * @since 4.4.0 766 * 767 * @param string $content The current post excerpt. 768 * @return string The modified post excerpt. 769 */ 770 function wp_oembed_excerpt_attachment( $content ) { 771 if ( is_attachment() ) { 772 return prepend_attachment( '' ); 773 } 774 775 return $content; 776 } -
src/wp-includes/query.php
diff --git src/wp-includes/query.php src/wp-includes/query.php index b93d027..bd4cdd0 100644
function is_404() { 719 719 } 720 720 721 721 /** 722 * Is the query for an embedded post? 723 * 724 * @since 4.4.0 725 * 726 * @global WP_Query $wp_query Global WP_Query instance. 727 * 728 * @return bool Whether we're in an embedded post or not. 729 */ 730 function is_embed() { 731 global $wp_query; 732 733 if ( ! isset( $wp_query ) ) { 734 _doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' ); 735 return false; 736 } 737 738 return $wp_query->is_embed(); 739 } 740 741 /** 722 742 * Is the query the main query? 723 743 * 724 744 * @since 3.3.0 … … class WP_Query { 1201 1221 public $is_404 = false; 1202 1222 1203 1223 /** 1224 * Set if query is embed. 1225 * 1226 * @since 4.4.0 1227 * @access public 1228 * @var bool 1229 */ 1230 public $is_embed = false; 1231 1232 /** 1204 1233 * Set if query is within comments popup window. 1205 1234 * 1206 1235 * @since 1.5.0 … … class WP_Query { 1845 1874 if ( '404' == $qv['error'] ) 1846 1875 $this->set_404(); 1847 1876 1877 $this->is_embed = isset( $qv['embed'] ) && ( $this->is_singular || $this->is_404 ); 1878 1848 1879 $this->query_vars_hash = md5( serialize( $this->query_vars ) ); 1849 1880 $this->query_vars_changed = false; 1850 1881 … … class WP_Query { 4635 4666 } 4636 4667 4637 4668 /** 4669 * Is the query for an embedded post? 4670 * 4671 * @since 3.1.0 4672 * 4673 * @return bool 4674 */ 4675 public function is_embed() { 4676 return (bool) $this->is_embed; 4677 } 4678 4679 /** 4638 4680 * Is the query the main query? 4639 4681 * 4640 4682 * @since 3.3.0 -
src/wp-includes/script-loader.php
diff --git src/wp-includes/script-loader.php src/wp-includes/script-loader.php index 1b28da5..a18bd49 100644
function wp_default_scripts( &$scripts ) { 466 466 ), 467 467 ) ); 468 468 469 $scripts->add( 'wp-oembed', "/wp-includes/js/wp-oembed$suffix.js" ); 470 469 471 // To enqueue media-views or media-editor, call wp_enqueue_media(). 470 472 // Both rely on numerous settings, styles, and templates to operate correctly. 471 473 $scripts->add( 'media-views', "/wp-includes/js/media-views$suffix.js", array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement' ), false, 1 ); -
src/wp-includes/template-loader.php
diff --git src/wp-includes/template-loader.php src/wp-includes/template-loader.php index 95216fe..d3eebe9 100644
elseif ( is_feed() ) : 39 39 elseif ( is_trackback() ) : 40 40 include( ABSPATH . 'wp-trackback.php' ); 41 41 return; 42 elseif ( is_embed() ) : 43 $template = ABSPATH . WPINC . '/embed-template.php'; 44 45 /** 46 * Filter the template used for embedded posts. 47 * 48 * @since 4.4.0 49 * 50 * @param string $template Path to the template file. 51 */ 52 $template = apply_filters( 'embed_template', $template ); 53 54 include ( $template ); 55 return; 42 56 endif; 43 57 44 58 if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) : -
src/wp-settings.php
diff --git src/wp-settings.php src/wp-settings.php index 993a120..5046900 100644
require( ABSPATH . WPINC . '/update.php' ); 146 146 require( ABSPATH . WPINC . '/canonical.php' ); 147 147 require( ABSPATH . WPINC . '/shortcodes.php' ); 148 148 require( ABSPATH . WPINC . '/class-wp-embed.php' ); 149 require( ABSPATH . WPINC . '/class-wp-oembed-controller.php' ); 150 require( ABSPATH . WPINC . '/oembed-functions.php' ); 149 151 require( ABSPATH . WPINC . '/media.php' ); 150 152 require( ABSPATH . WPINC . '/http.php' ); 151 153 require( ABSPATH . WPINC . '/widgets.php' ); -
new file tests/phpunit/tests/oembed/controller.php
diff --git tests/phpunit/tests/oembed/controller.php tests/phpunit/tests/oembed/controller.php new file mode 100644 index 0000000..4752421
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Test_oEmbed_Controller extends WP_UnitTestCase { 7 function test_request_with_bad_url() { 8 $request = array( 9 'url' => '', 10 'format' => 'json', 11 'maxwidth' => 600, 12 ); 13 14 $legacy_controller = new WP_oEmbed_Controller(); 15 16 $this->assertEquals( 'Invalid URL.', $legacy_controller->dispatch( $request ) ); 17 } 18 19 function test_request_json() { 20 $user = $this->factory->user->create_and_get( array( 21 'display_name' => 'John Doe', 22 ) ); 23 $post = $this->factory->post->create_and_get( array( 24 'post_author' => $user->ID, 25 'post_title' => 'Hello World', 26 ) ); 27 28 // WP_Query arguments. 29 $request = array( 30 'url' => get_permalink( $post->ID ), 31 'format' => 'json', 32 'maxwidth' => 400, 33 'callback' => '', 34 'oembed' => true, 35 ); 36 37 $legacy_controller = new WP_oEmbed_Controller(); 38 39 $data = json_decode( $legacy_controller->dispatch( $request ), true ); 40 41 $this->assertTrue( is_array( $data ) ); 42 43 $this->assertArrayHasKey( 'version', $data ); 44 $this->assertArrayHasKey( 'provider_name', $data ); 45 $this->assertArrayHasKey( 'provider_url', $data ); 46 $this->assertArrayHasKey( 'author_name', $data ); 47 $this->assertArrayHasKey( 'author_url', $data ); 48 $this->assertArrayHasKey( 'title', $data ); 49 $this->assertArrayHasKey( 'type', $data ); 50 $this->assertArrayHasKey( 'width', $data ); 51 52 $this->assertEquals( '1.0', $data['version'] ); 53 $this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] ); 54 $this->assertEquals( get_home_url(), $data['provider_url'] ); 55 $this->assertEquals( $user->display_name, $data['author_name'] ); 56 $this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] ); 57 $this->assertEquals( $post->post_title, $data['title'] ); 58 $this->assertEquals( 'rich', $data['type'] ); 59 $this->assertTrue( $data['width'] <= $request['maxwidth'] ); 60 } 61 62 function test_request_jsonp() { 63 $user = $this->factory->user->create_and_get( array( 64 'display_name' => 'John Doe', 65 ) ); 66 $post = $this->factory->post->create_and_get( array( 67 'post_author' => $user->ID, 68 'post_title' => 'Hello World', 69 ) ); 70 71 $request = array( 72 'url' => get_permalink( $post->ID ), 73 'format' => 'json', 74 'maxwidth' => 600, 75 'callback' => 'mycallback', 76 ); 77 78 $legacy_controller = new WP_oEmbed_Controller(); 79 80 $data = $legacy_controller->dispatch( $request ); 81 82 $this->assertEquals( 0, strpos( $data, '/**/mycallback(' ) ); 83 } 84 85 function test_request_jsonp_invalid_callback() { 86 $user = $this->factory->user->create_and_get( array( 87 'display_name' => 'John Doe', 88 ) ); 89 $post = $this->factory->post->create_and_get( array( 90 'post_author' => $user->ID, 91 'post_title' => 'Hello World', 92 ) ); 93 94 $request = array( 95 'url' => get_permalink( $post->ID ), 96 'format' => 'json', 97 'maxwidth' => 600, 98 'callback' => array( 'foo', 'bar' ), 99 ); 100 101 $legacy_controller = new WP_oEmbed_Controller(); 102 103 $data = $legacy_controller->dispatch( $request ); 104 105 $this->assertFalse( strpos( $data, '/**/' ) ); 106 } 107 108 function test_request_json_invalid_data() { 109 $request = array( 110 'callback' => '', 111 ); 112 113 $legacy_controller = new WP_oEmbed_Controller(); 114 115 $this->assertEquals( 'Not implemented', $legacy_controller->json_response( null, $request ) ); 116 $this->assertEquals( 'Not implemented', $legacy_controller->json_response( 123, $request ) ); 117 $this->assertEquals( 'Not implemented', $legacy_controller->json_response( array(), $request ) ); 118 } 119 120 function test_request_xml() { 121 $user = $this->factory->user->create_and_get( array( 122 'display_name' => 'John Doe', 123 ) ); 124 $post = $this->factory->post->create_and_get( array( 125 'post_author' => $user->ID, 126 'post_title' => 'Hello World', 127 ) ); 128 129 $request = array( 130 'url' => get_permalink( $post->ID ), 131 'format' => 'xml', 132 'maxwidth' => 400, 133 'callback' => '', 134 ); 135 136 $legacy_controller = new WP_oEmbed_Controller(); 137 138 $data = $legacy_controller->dispatch( $request ); 139 140 $data = simplexml_load_string( $data ); 141 $this->assertInstanceOf( 'SimpleXMLElement', $data ); 142 143 $data = (array) $data; 144 145 $this->assertArrayHasKey( 'version', $data ); 146 $this->assertArrayHasKey( 'provider_name', $data ); 147 $this->assertArrayHasKey( 'provider_url', $data ); 148 $this->assertArrayHasKey( 'author_name', $data ); 149 $this->assertArrayHasKey( 'author_url', $data ); 150 $this->assertArrayHasKey( 'title', $data ); 151 $this->assertArrayHasKey( 'type', $data ); 152 $this->assertArrayHasKey( 'width', $data ); 153 154 $this->assertEquals( '1.0', $data['version'] ); 155 $this->assertEquals( get_bloginfo( 'name' ), $data['provider_name'] ); 156 $this->assertEquals( get_home_url(), $data['provider_url'] ); 157 $this->assertEquals( $user->display_name, $data['author_name'] ); 158 $this->assertEquals( get_author_posts_url( $user->ID, $user->user_nicename ), $data['author_url'] ); 159 $this->assertEquals( $post->post_title, $data['title'] ); 160 $this->assertEquals( 'rich', $data['type'] ); 161 $this->assertTrue( $data['width'] <= $request['maxwidth'] ); 162 } 163 164 function test_request_xml_invalid_data() { 165 $legacy_controller = new WP_oEmbed_Controller(); 166 167 $this->assertEquals( 'Not implemented', $legacy_controller->xml_response( null ) ); 168 $this->assertEquals( 'Not implemented', $legacy_controller->xml_response( 123 ) ); 169 $this->assertEquals( 'Not implemented', $legacy_controller->xml_response( array() ) ); 170 } 171 172 /** 173 * @group multisite 174 */ 175 function test_request_ms_child_in_root_blog() { 176 if ( ! is_multisite() ) { 177 $this->markTestSkipped( __METHOD__ . ' is a multisite-only test.' ); 178 } 179 180 $child = $this->factory->blog->create(); 181 182 switch_to_blog( $child ); 183 184 $post = $this->factory->post->create_and_get( array( 185 'post_title' => 'Hello Child Blog', 186 ) ); 187 188 $request = array( 189 'url' => get_permalink( $post->ID ), 190 'format' => 'json', 191 'maxwidth' => 600, 192 'callback' => '', 193 ); 194 195 $legacy_controller = new WP_oEmbed_Controller(); 196 197 $data = json_decode( $legacy_controller->dispatch( $request ), true ); 198 199 $this->assertInternalType( 'array', $data ); 200 $this->assertNotEmpty( $data ); 201 202 restore_current_blog(); 203 } 204 205 function test_get_oembed_endpoint_url() { 206 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url() ); 207 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'json' ) ); 208 $this->assertEquals( home_url() . '/?oembed=true', get_oembed_endpoint_url( '', 'xml' ) ); 209 210 $post_id = $this->factory->post->create(); 211 $url = get_permalink( $post_id ); 212 213 $this->assertEquals( home_url() . '/?oembed=true&url=' . $url, get_oembed_endpoint_url( $url ) ); 214 $this->assertEquals( home_url() . '/?oembed=true&url=' . $url . '&format=xml', get_oembed_endpoint_url( $url, 'xml' ) ); 215 } 216 217 function test_wp_oembed_ensure_format() { 218 $this->assertEquals( 'json', wp_oembed_ensure_format( 'json' ) ); 219 $this->assertEquals( 'xml', wp_oembed_ensure_format( 'xml' ) ); 220 $this->assertEquals( 'json', wp_oembed_ensure_format( 123 ) ); 221 $this->assertEquals( 'json', wp_oembed_ensure_format( 'random' ) ); 222 $this->assertEquals( 'json', wp_oembed_ensure_format( array() ) ); 223 } 224 225 function test_oembed_create_xml() { 226 $actual = _oembed_create_xml( array( 227 'foo' => 'bar', 228 'bar' => 'baz', 229 'ping' => 'pong', 230 ) ); 231 232 $expected = '<oembed><foo>bar</foo><bar>baz</bar><ping>pong</ping></oembed>'; 233 234 $this->assertStringEndsWith( $expected, trim( $actual ) ); 235 236 $actual = _oembed_create_xml( array( 237 'foo' => array( 238 'bar' => 'baz', 239 ), 240 'ping' => 'pong', 241 ) ); 242 243 $expected = '<oembed><foo><bar>baz</bar></foo><ping>pong</ping></oembed>'; 244 245 $this->assertStringEndsWith( $expected, trim( $actual ) ); 246 247 $actual = _oembed_create_xml( array( 248 'foo' => array( 249 'bar' => array( 250 'ping' => 'pong', 251 ), 252 ), 253 'hello' => 'world', 254 ) ); 255 256 $expected = '<oembed><foo><bar><ping>pong</ping></bar></foo><hello>world</hello></oembed>'; 257 258 $this->assertStringEndsWith( $expected, trim( $actual ) ); 259 260 $actual = _oembed_create_xml( array( 261 array( 262 'foo' => array( 263 'bar', 264 ), 265 ), 266 'helloworld', 267 ) ); 268 269 $expected = '<oembed><oembed><foo><oembed>bar</oembed></foo></oembed><oembed>helloworld</oembed></oembed>'; 270 271 $this->assertStringEndsWith( $expected, trim( $actual ) ); 272 } 273 } -
new file tests/phpunit/tests/oembed/discovery.php
diff --git tests/phpunit/tests/oembed/discovery.php tests/phpunit/tests/oembed/discovery.php new file mode 100644 index 0000000..cad47cf
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Tests_oEmbed_Discovery extends WP_UnitTestCase { 7 function test_add_oembed_discovery_links_non_singular() { 8 ob_start(); 9 wp_oembed_add_discovery_links(); 10 $actual = ob_get_clean(); 11 $this->assertSame( '', $actual ); 12 } 13 14 function test_add_oembed_discovery_links_to_post() { 15 $post_id = $this->factory->post->create(); 16 $this->go_to( get_permalink( $post_id ) ); 17 18 $this->assertQueryTrue( 'is_single', 'is_singular' ); 19 20 ob_start(); 21 wp_oembed_add_discovery_links(); 22 $actual = ob_get_clean(); 23 24 $expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n"; 25 $expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n"; 26 27 $this->assertEquals( $expected, $actual ); 28 } 29 30 function test_add_oembed_discovery_links_to_page() { 31 $post_id = $this->factory->post->create( array( 32 'post_type' => 'page' 33 )); 34 $this->go_to( get_permalink( $post_id ) ); 35 36 $this->assertQueryTrue( 'is_page', 'is_singular' ); 37 38 ob_start(); 39 wp_oembed_add_discovery_links(); 40 $actual = ob_get_clean(); 41 42 $expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n"; 43 $expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n"; 44 45 $this->assertEquals( $expected, $actual ); 46 } 47 48 function test_add_oembed_discovery_links_to_attachment() { 49 $post_id = $this->factory->post->create(); 50 $file = DIR_TESTDATA . '/images/canola.jpg'; 51 $attachment_id = $this->factory->attachment->create_object( $file, $post_id, array( 52 'post_mime_type' => 'image/jpeg', 53 ) ); 54 55 $this->go_to( get_permalink( $attachment_id ) ); 56 57 $this->assertQueryTrue( 'is_attachment', 'is_singular', 'is_single' ); 58 59 ob_start(); 60 wp_oembed_add_discovery_links(); 61 $actual = ob_get_clean(); 62 63 $expected = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n"; 64 $expected .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n"; 65 66 $this->assertEquals( $expected, $actual ); 67 } 68 } -
new file tests/phpunit/tests/oembed/filterResult.php
diff --git tests/phpunit/tests/oembed/filterResult.php tests/phpunit/tests/oembed/filterResult.php new file mode 100644 index 0000000..cfe5c98
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Tests_Filter_oEmbed_Result extends WP_UnitTestCase { 7 function test_filter_oembed_result_trusted_malicious_iframe() { 8 $html = '<p></p><iframe onload="alert(1)"></iframe>'; 9 10 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' ); 11 12 $this->assertEquals( $html, $actual ); 13 } 14 15 function test_filter_oembed_result_with_untrusted_provider() { 16 $html = '<p></p><iframe onload="alert(1)" src="http://example.com/sample-page/"></iframe>'; 17 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), 'http://example.com/sample-page/' ); 18 19 $matches = array(); 20 preg_match( '|src=".*#\?secret=([\w\d]+)" data-secret="([\w\d]+)"|', $actual, $matches ); 21 22 $this->assertTrue( isset( $matches[1] ) ); 23 $this->assertTrue( isset( $matches[2] ) ); 24 $this->assertEquals( $matches[1], $matches[2] ); 25 } 26 27 function test_filter_oembed_result_only_one_iframe_is_allowed() { 28 $html = '<div><iframe></iframe><iframe></iframe><p></p></div>'; 29 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), '' ); 30 31 $this->assertEquals( '<iframe sandbox="allow-scripts" security="restricted"></iframe>', $actual ); 32 } 33 34 function test_filter_oembed_result_with_newlines() { 35 $html = <<<EOD 36 <script>var = 1;</script> 37 <iframe></iframe> 38 <iframe></iframe> 39 <p></p> 40 EOD; 41 42 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), '' ); 43 44 $this->assertEquals( '<iframe sandbox="allow-scripts" security="restricted"></iframe>', $actual ); 45 } 46 47 function test_filter_oembed_result_without_iframe() { 48 $html = '<span>Hello</span><p>World</p>'; 49 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), '' ); 50 51 $this->assertFalse( $actual ); 52 53 $html = '<div><p></p></div><script></script>'; 54 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), '' ); 55 56 $this->assertFalse( $actual ); 57 } 58 59 function test_filter_oembed_result_secret_param_available() { 60 $html = '<iframe src="https://wordpress.org"></iframe>'; 61 $actual = wp_filter_oembed_result( $html, (object) array( 'type' => 'rich' ), '' ); 62 63 $matches = array(); 64 preg_match( '|src="https://wordpress.org#\?secret=([\w\d]+)" data-secret="([\w\d]+)"|', $actual, $matches ); 65 66 $this->assertTrue( isset( $matches[1] ) ); 67 $this->assertTrue( isset( $matches[2] ) ); 68 $this->assertEquals( $matches[1], $matches[2] ); 69 } 70 71 function test_filter_oembed_result_wrong_type_provided() { 72 $actual = wp_filter_oembed_result( 'some string', (object) array( 'type' => 'link' ), '' ); 73 74 $this->assertEquals( 'some string', $actual ); 75 } 76 77 function test_filter_oembed_result_invalid_result() { 78 $this->assertFalse( wp_filter_oembed_result( false, (object) array( 'type' => 'rich' ), '' ) ); 79 $this->assertFalse( wp_filter_oembed_result( '', (object) array( 'type' => 'rich' ), '' ) ); 80 } 81 } -
new file tests/phpunit/tests/oembed/getResponseData.php
diff --git tests/phpunit/tests/oembed/getResponseData.php tests/phpunit/tests/oembed/getResponseData.php new file mode 100644 index 0000000..3f37a21
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Tests_oEmbed_Response_Data extends WP_UnitTestCase { 7 function test_get_oembed_response_data_non_existent_post() { 8 $this->assertFalse( get_oembed_response_data( 0, 100 ) ); 9 } 10 11 function test_get_oembed_response_data() { 12 $post = $this->factory->post->create_and_get( array( 13 'post_title' => 'Some Post', 14 ) ); 15 16 $data = get_oembed_response_data( $post, 400 ); 17 18 $this->assertEqualSets( array( 19 'version' => '1.0', 20 'provider_name' => get_bloginfo( 'name' ), 21 'provider_url' => get_home_url( '/' ), 22 'author_name' => get_bloginfo( 'name' ), 23 'author_url' => get_home_url( '/' ), 24 'title' => 'Some Post', 25 'type' => 'rich', 26 'width' => 400, 27 'height' => 225, 28 'html' => get_post_embed_html( $post, 400, 225 ), 29 ), $data ); 30 } 31 32 /** 33 * Test get_oembed_response_data with an author. 34 */ 35 function test_get_oembed_response_data_author() { 36 $user_id = $this->factory->user->create( array( 37 'display_name' => 'John Doe', 38 ) ); 39 40 $post = $this->factory->post->create_and_get( array( 41 'post_title' => 'Some Post', 42 'post_author' => $user_id, 43 ) ); 44 45 $data = get_oembed_response_data( $post, 400 ); 46 47 $this->assertEqualSets( array( 48 'version' => '1.0', 49 'provider_name' => get_bloginfo( 'name' ), 50 'provider_url' => get_home_url( '/' ), 51 'author_name' => 'John Doe', 52 'author_url' => get_author_posts_url( $user_id ), 53 'title' => 'Some Post', 54 'type' => 'rich', 55 'width' => 400, 56 'height' => 225, 57 'html' => get_post_embed_html( $post, 400, 225 ), 58 ), $data ); 59 } 60 61 function test_get_oembed_response_link() { 62 remove_filter( 'oembed_response_data', 'get_oembed_response_data_rich' ); 63 64 $post = $this->factory->post->create_and_get( array( 65 'post_title' => 'Some Post', 66 ) ); 67 68 $data = get_oembed_response_data( $post, 600 ); 69 70 $this->assertEqualSets( array( 71 'version' => '1.0', 72 'provider_name' => get_bloginfo( 'name' ), 73 'provider_url' => get_home_url( '/' ), 74 'author_name' => get_bloginfo( 'name' ), 75 'author_url' => get_home_url( '/' ), 76 'title' => 'Some Post', 77 'type' => 'link', 78 ), $data ); 79 80 add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 ); 81 } 82 83 function test_get_oembed_response_data_with_draft_post() { 84 $post = $this->factory->post->create_and_get( array( 85 'post_status' => 'draft', 86 ) ); 87 88 $this->assertFalse( get_oembed_response_data( $post, 100 ) ); 89 } 90 91 function test_get_oembed_response_data_with_scheduled_post() { 92 $post = $this->factory->post->create_and_get( array( 93 'post_status' => 'future', 94 'post_date' => strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 day' ) ), 95 ) ); 96 97 $this->assertFalse( get_oembed_response_data( $post, 100 ) ); 98 } 99 100 function test_get_oembed_response_data_with_private_post() { 101 $post = $this->factory->post->create_and_get( array( 102 'post_status' => 'private', 103 ) ); 104 105 $this->assertFalse( get_oembed_response_data( $post, 100 ) ); 106 } 107 108 function test_get_oembed_response_data_maxwidth_too_high() { 109 $post = $this->factory->post->create_and_get(); 110 111 $data = get_oembed_response_data( $post, 1000 ); 112 113 $this->assertEquals( 600, $data['width'] ); 114 $this->assertEquals( 338, $data['height'] ); 115 } 116 117 function test_get_oembed_response_data_maxwidth_too_low() { 118 $post = $this->factory->post->create_and_get(); 119 120 $data = get_oembed_response_data( $post, 100 ); 121 122 $this->assertEquals( 200, $data['width'] ); 123 $this->assertEquals( 200, $data['height'] ); 124 } 125 126 function test_get_oembed_response_data_with_thumbnail() { 127 $post = $this->factory->post->create_and_get(); 128 $file = DIR_TESTDATA . '/images/canola.jpg'; 129 $attachment_id = $this->factory->attachment->create_object( $file, $post->ID, array( 130 'post_mime_type' => 'image/jpeg', 131 ) ); 132 set_post_thumbnail( $post, $attachment_id ); 133 134 $data = get_oembed_response_data( $post, 400 ); 135 136 $this->assertArrayHasKey( 'thumbnail_url', $data ); 137 $this->assertArrayHasKey( 'thumbnail_width', $data ); 138 $this->assertArrayHasKey( 'thumbnail_height', $data ); 139 $this->assertTrue( 400 >= $data['thumbnail_width'] ); 140 } 141 142 function test_get_oembed_response_data_for_attachment() { 143 $parent = $this->factory->post->create(); 144 $file = DIR_TESTDATA . '/images/canola.jpg'; 145 $post = $this->factory->attachment->create_object( $file, $parent, array( 146 'post_mime_type' => 'image/jpeg', 147 ) ); 148 149 $data = get_oembed_response_data( $post, 400 ); 150 151 $this->assertArrayHasKey( 'thumbnail_url', $data ); 152 $this->assertArrayHasKey( 'thumbnail_width', $data ); 153 $this->assertArrayHasKey( 'thumbnail_height', $data ); 154 $this->assertTrue( 400 >= $data['thumbnail_width'] ); 155 } 156 } -
new file tests/phpunit/tests/oembed/headers.php
diff --git tests/phpunit/tests/oembed/headers.php tests/phpunit/tests/oembed/headers.php new file mode 100644 index 0000000..f2e8979
- + 1 <?php 2 3 /** 4 * @runTestsInSeparateProcesses 5 * @group oembed 6 */ 7 class Tests_oEmbed_HTTP_Headers extends WP_UnitTestCase { 8 function test_request_json_response_headers() { 9 if ( ! function_exists( 'xdebug_get_headers' ) ) { 10 $this->markTestSkipped( 'xdebug is required for this test' ); 11 } 12 13 $post = $this->factory->post->create_and_get( array( 14 'post_title' => 'Hello World', 15 ) ); 16 17 $request = array( 18 'url' => get_permalink( $post->ID ), 19 'format' => 'json', 20 'maxwidth' => 600, 21 'callback' => '', 22 ); 23 24 $legacy_controller = new WP_oEmbed_Controller(); 25 $legacy_controller->dispatch( $request ); 26 27 $headers = xdebug_get_headers(); 28 29 $this->assertTrue( in_array( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ), $headers ) ); 30 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) ); 31 32 $request['callback'] = 'foobar'; 33 34 $legacy_controller->dispatch( $request ); 35 36 $headers = xdebug_get_headers(); 37 38 $this->assertTrue( in_array( 'Content-Type: application/javascript; charset=' . get_option( 'blog_charset' ), $headers ) ); 39 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) ); 40 } 41 42 function test_request_xml_response_headers() { 43 if ( ! function_exists( 'xdebug_get_headers' ) ) { 44 $this->markTestSkipped( 'xdebug is required for this test' ); 45 } 46 47 $post = $this->factory->post->create_and_get( array( 48 'post_title' => 'Hello World', 49 ) ); 50 51 $request = array( 52 'url' => get_permalink( $post->ID ), 53 'format' => 'xml', 54 'maxwidth' => 600, 55 ); 56 57 $legacy_controller = new WP_oEmbed_Controller(); 58 $legacy_controller->dispatch( $request ); 59 60 $headers = xdebug_get_headers(); 61 62 $this->assertTrue( in_array( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), $headers ) ); 63 } 64 } -
new file tests/phpunit/tests/oembed/postEmbedUrl.php
diff --git tests/phpunit/tests/oembed/postEmbedUrl.php tests/phpunit/tests/oembed/postEmbedUrl.php new file mode 100644 index 0000000..26e57ce
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Tests_Post_Embed_URL extends WP_UnitTestCase { 7 function test_get_post_embed_url_non_existent_post() { 8 $embed_url = get_post_embed_url( 0 ); 9 $this->assertFalse( $embed_url ); 10 } 11 12 function test_get_post_embed_url_with_pretty_permalinks() { 13 update_option( 'permalink_structure', '/%postname%' ); 14 15 $post_id = $this->factory->post->create(); 16 $permalink = get_permalink( $post_id ); 17 $embed_url = get_post_embed_url( $post_id ); 18 19 $this->assertEquals( user_trailingslashit( trailingslashit( $permalink ) . 'embed' ), $embed_url ); 20 21 update_option( 'permalink_structure', '' ); 22 } 23 24 function test_get_post_embed_url_with_ugly_permalinks() { 25 $post_id = $this->factory->post->create(); 26 $permalink = get_permalink( $post_id ); 27 $embed_url = get_post_embed_url( $post_id ); 28 29 $this->assertEquals( $permalink . '&embed=true', $embed_url ); 30 } 31 } -
new file tests/phpunit/tests/oembed/template.php
diff --git tests/phpunit/tests/oembed/template.php tests/phpunit/tests/oembed/template.php new file mode 100644 index 0000000..2c97d2c
- + 1 <?php 2 3 /** 4 * @group oembed 5 */ 6 class Tests_Embed_Template extends WP_UnitTestCase { 7 function test_oembed_output_post() { 8 $user = $this->factory->user->create_and_get( array( 9 'display_name' => 'John Doe', 10 ) ); 11 12 $post_id = $this->factory->post->create( array( 13 'post_author' => $user->ID, 14 'post_title' => 'Hello World', 15 'post_content' => 'Foo Bar', 16 'post_excerpt' => 'Bar Baz', 17 ) ); 18 $this->go_to( get_post_embed_url( $post_id ) ); 19 20 $this->assertQueryTrue( 'is_single', 'is_singular' ); 21 22 ob_start(); 23 include( ABSPATH . WPINC . '/embed-template.php' ); 24 $actual = ob_get_clean(); 25 26 $doc = new DOMDocument(); 27 $this->assertTrue( $doc->loadHTML( $actual ) ); 28 $this->assertTrue( false === strpos( $actual, 'Page not found' ) ); 29 $this->assertTrue( false !== strpos( $actual, 'Hello World' ) ); 30 } 31 32 function test_oembed_output_post_with_thumbnail() { 33 $post_id = $this->factory->post->create( array( 34 'post_title' => 'Hello World', 35 'post_content' => 'Foo Bar', 36 'post_excerpt' => 'Bar Baz', 37 ) ); 38 $file = DIR_TESTDATA . '/images/canola.jpg'; 39 $attachment_id = $this->factory->attachment->create_object( $file, $post_id, array( 40 'post_mime_type' => 'image/jpeg', 41 ) ); 42 set_post_thumbnail( $post_id, $attachment_id ); 43 44 $this->go_to( get_post_embed_url( $post_id ) ); 45 46 $this->assertQueryTrue( 'is_single', 'is_singular' ); 47 48 ob_start(); 49 include( ABSPATH . WPINC . '/embed-template.php' ); 50 $actual = ob_get_clean(); 51 52 $doc = new DOMDocument(); 53 $this->assertTrue( $doc->loadHTML( $actual ) ); 54 $this->assertFalse( strpos( $actual, 'Page not found' ) ); 55 $this->assertTrue( false !== strpos( $actual, 'Hello World' ) ); 56 $this->assertTrue( false !== strpos( $actual, 'canola.jpg' ) ); 57 } 58 59 function test_oembed_output_404() { 60 $this->go_to( home_url( '/?p=123&embed=true' ) ); 61 $GLOBALS['wp_query']->query_vars['embed'] = true; 62 63 $this->assertQueryTrue( 'is_404' ); 64 65 ob_start(); 66 include( ABSPATH . WPINC . '/embed-template.php' ); 67 $actual = ob_get_clean(); 68 69 $doc = new DOMDocument(); 70 $this->assertTrue( $doc->loadHTML( $actual ) ); 71 $this->assertTrue( false !== strpos( $actual, 'Page not found' ) ); 72 } 73 74 function test_oembed_output_attachment() { 75 $post = $this->factory->post->create_and_get(); 76 $file = DIR_TESTDATA . '/images/canola.jpg'; 77 $attachment_id = $this->factory->attachment->create_object( $file, $post->ID, array( 78 'post_mime_type' => 'image/jpeg', 79 'post_title' => 'Hello World', 80 'post_content' => 'Foo Bar', 81 'post_excerpt' => 'Bar Baz', 82 ) ); 83 84 $this->go_to( get_post_embed_url( $attachment_id ) ); 85 86 $this->assertQueryTrue( 'is_single', 'is_singular', 'is_attachment' ); 87 88 ob_start(); 89 include( ABSPATH . WPINC . '/embed-template.php' ); 90 $actual = ob_get_clean(); 91 92 $doc = new DOMDocument(); 93 $this->assertTrue( $doc->loadHTML( $actual ) ); 94 $this->assertFalse( strpos( $actual, 'Page not found' ) ); 95 $this->assertTrue( false !== strpos( $actual, 'Hello World' ) ); 96 $this->assertTrue( false !== strpos( $actual, 'canola.jpg' ) ); 97 } 98 99 function test_oembed_output_draft_post() { 100 $post_id = $this->factory->post->create( array( 101 'post_title' => 'Hello World', 102 'post_content' => 'Foo Bar', 103 'post_excerpt' => 'Bar Baz', 104 'post_status' => 'draft', 105 ) ); 106 107 $this->go_to( get_post_embed_url( $post_id ) ); 108 109 $this->assertQueryTrue( 'is_404' ); 110 111 ob_start(); 112 include( ABSPATH . WPINC . '/embed-template.php' ); 113 $actual = ob_get_clean(); 114 115 $doc = new DOMDocument(); 116 $this->assertTrue( $doc->loadHTML( $actual ) ); 117 $this->assertTrue( false !== strpos( $actual, 'Page not found' ) ); 118 } 119 120 function test_oembed_output_scheduled_post() { 121 $post_id = $this->factory->post->create( array( 122 'post_title' => 'Hello World', 123 'post_content' => 'Foo Bar', 124 'post_excerpt' => 'Bar Baz', 125 'post_status' => 'future', 126 'post_date' => strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 day' ) ), 127 ) ); 128 129 $this->go_to( get_post_embed_url( $post_id ) ); 130 131 $this->assertQueryTrue( 'is_404' ); 132 133 ob_start(); 134 include( ABSPATH . WPINC . '/embed-template.php' ); 135 $actual = ob_get_clean(); 136 137 $doc = new DOMDocument(); 138 $this->assertTrue( $doc->loadHTML( $actual ) ); 139 $this->assertTrue( false !== strpos( $actual, 'Page not found' ) ); 140 } 141 142 function test_oembed_output_private_post() { 143 $post_id = $this->factory->post->create( array( 144 'post_title' => 'Hello World', 145 'post_content' => 'Foo Bar', 146 'post_excerpt' => 'Bar Baz', 147 'post_status' => 'private', 148 ) ); 149 150 $this->go_to( get_post_embed_url( $post_id ) ); 151 152 $this->assertQueryTrue( 'is_404' ); 153 154 ob_start(); 155 include( ABSPATH . WPINC . '/embed-template.php' ); 156 $actual = ob_get_clean(); 157 158 $doc = new DOMDocument(); 159 $this->assertTrue( $doc->loadHTML( $actual ) ); 160 $this->assertTrue( false !== strpos( $actual, 'Page not found' ) ); 161 } 162 163 function test_oembed_output_private_post_with_permissions() { 164 $user_id = $this->factory->user->create( array( 'role' => 'editor' ) ); 165 wp_set_current_user( $user_id ); 166 167 $post_id = $this->factory->post->create( array( 168 'post_title' => 'Hello World', 169 'post_content' => 'Foo Bar', 170 'post_excerpt' => 'Bar Baz', 171 'post_status' => 'private', 172 'post_author' => $user_id, 173 ) ); 174 175 $this->go_to( get_post_embed_url( $post_id ) ); 176 177 $this->assertQueryTrue( 'is_single', 'is_singular' ); 178 179 ob_start(); 180 include( ABSPATH . WPINC . '/embed-template.php' ); 181 $actual = ob_get_clean(); 182 183 $doc = new DOMDocument(); 184 $this->assertTrue( $doc->loadHTML( $actual ) ); 185 $this->assertTrue( false === strpos( $actual, 'Page not found' ) ); 186 $this->assertTrue( false !== strpos( $actual, 'Hello World' ) ); 187 } 188 189 function test_wp_oembed_excerpt_more_no_embed() { 190 $GLOBALS['wp_query'] = new WP_Query(); 191 192 $this->assertEquals( 'foo bar', wp_oembed_excerpt_more( 'foo bar' ) ); 193 } 194 195 function test_wp_oembed_excerpt_more() { 196 $post_id = $this->factory->post->create( array( 197 'post_content' => 'Foo Bar', 198 ) ); 199 200 $this->assertEquals( '', wp_oembed_excerpt_more( '' ) ); 201 202 $this->go_to( get_post_embed_url( $post_id ) ); 203 204 $actual = wp_oembed_excerpt_more( '' ); 205 206 $expected = sprintf( 207 '… <a class="wp-embed-more" href="%s" target="_top">Read more</a>', 208 get_the_permalink() 209 ); 210 211 $this->assertEquals( $expected, $actual ); 212 } 213 214 function test_is_embed_post() { 215 $this->assertFalse( is_embed() ); 216 217 $post_id = $this->factory->post->create(); 218 $this->go_to( get_post_embed_url( $post_id ) ); 219 $this->assertTrue( is_embed() ); 220 } 221 222 function test_is_embed_attachment() { 223 $post_id = $this->factory->post->create(); 224 $file = DIR_TESTDATA . '/images/canola.jpg'; 225 $attachment_id = $this->factory->attachment->create_object( $file, $post_id, array( 226 'post_mime_type' => 'image/jpeg', 227 ) ); 228 $this->go_to( get_post_embed_url( $attachment_id ) ); 229 $this->assertTrue( is_embed() ); 230 } 231 232 function test_is_embed_404() { 233 $this->go_to( home_url( '/?p=12345&embed=true' ) ); 234 $this->assertTrue( is_embed() ); 235 } 236 237 function test_get_post_embed_html_non_existent_post() { 238 $this->assertFalse( get_post_embed_html( 0, 200, 200 ) ); 239 $this->assertFalse( get_post_embed_html( null, 200, 200 ) ); 240 } 241 242 function test_get_post_embed_html() { 243 $post_id = $this->factory->post->create(); 244 245 $expected = '<iframe sandbox="allow-scripts" security="restricted" src="' . esc_url( get_post_embed_url( $post_id ) ) . '" width="200" height="200" title="Embedded WordPress Post" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" class="wp-embedded-content"></iframe>'; 246 247 $this->assertStringEndsWith( $expected, get_post_embed_html( $post_id, 200, 200 ) ); 248 } 249 250 function test_add_host_js() { 251 ob_start(); 252 wp_oembed_add_host_js(); 253 ob_end_clean(); 254 255 $this->assertTrue( wp_script_is( 'wp-oembed' ) ); 256 } 257 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)