Ticket #32522: 32522.7.diff
File 32522.7.diff, 88.1 KB (added by , 8 years ago) |
---|
-
Gruntfile.js
232 232 'wp-includes/css/*.css', 233 233 234 234 // Exceptions 235 '!wp-includes/css/dashicons.css' 235 '!wp-includes/css/dashicons.css', 236 '!wp-includes/css/wp-oembed-embed.css' 236 237 ] 237 238 }, 238 239 colors: { … … 528 529 emoji: { 529 530 src: BUILD_DIR + 'wp-includes/formatting.php', 530 531 dest: '.' 532 }, 533 oembed: { 534 src: BUILD_DIR + 'wp-includes/oembed-functions.php', 535 dest: '.' 531 536 } 532 537 }, 533 538 _watch: { … … 637 642 'clean:tinymce', 638 643 'concat:emoji', 639 644 'includes:emoji', 645 'includes:oembed', 640 646 'jsvalidate:build' 641 647 ] ); 642 648 -
src/wp-includes/admin-bar.php
898 898 if ( defined('XMLRPC_REQUEST') || defined('DOING_AJAX') || defined('IFRAME_REQUEST') ) 899 899 return false; 900 900 901 if ( is_embed() ) { 902 return false; 903 } 904 901 905 // Integrated into the admin. 902 906 if ( is_admin() ) 903 907 return true; -
src/wp-includes/class-wp-editor.php
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
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 ); -
src/wp-includes/class-wp-oembed-controller.php
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
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 ) { … … 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(); … … 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 … … 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 … … 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) ) { … … 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
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/css/wp-oembed-embed.css
1 html, body { 2 padding: 0; 3 margin: 0; 4 } 5 6 body { 7 font-family: sans-serif; 8 } 9 10 /* Text meant only for screen readers */ 11 .screen-reader-text { 12 clip: rect(1px, 1px, 1px, 1px); 13 height: 1px; 14 overflow: hidden; 15 position: absolute !important; 16 width: 1px; 17 } 18 19 /* Dashicons */ 20 .dashicons { 21 display: inline-block; 22 width: 20px; 23 height: 20px; 24 background-color: transparent; 25 background-repeat: no-repeat; 26 -webkit-background-size: 20px 20px; 27 background-size: 20px; 28 background-position: center; 29 -webkit-transition: background .1s ease-in; 30 transition: background .1s ease-in; 31 position: relative; 32 top: 5px; 33 } 34 35 .dashicons-no { 36 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"); 37 } 38 39 .dashicons-admin-comments { 40 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"); 41 } 42 43 .wp-embed-comments a:hover .dashicons-admin-comments { 44 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"); 45 } 46 47 .dashicons-share { 48 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"); 49 } 50 51 .wp-embed-share-dialog-open:hover .dashicons-share { 52 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"); 53 } 54 55 .wp-embed { 56 width: 100%; 57 padding: 25px; 58 font: 400 14px/1.5 'Open Sans', sans-serif; 59 color: #82878c; 60 background: white; 61 border: 1px solid #e5e5e5; 62 -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); 63 box-shadow: 0 1px 1px rgba(0, 0, 0, .05); 64 -webkit-box-sizing: border-box; 65 -moz-box-sizing: border-box; 66 box-sizing: border-box; 67 /* Clearfix */ 68 overflow: auto; 69 zoom: 1; 70 } 71 72 .wp-embed a { 73 color: #82878c; 74 text-decoration: none; 75 } 76 77 .wp-embed a:hover { 78 text-decoration: underline; 79 } 80 81 .wp-embed-featured-image { 82 margin-bottom: 20px; 83 } 84 85 .wp-embed-featured-image img { 86 width: 100%; 87 height: auto; 88 border: none; 89 } 90 91 .wp-embed-featured-image.square { 92 float: left; 93 max-width: 160px; 94 margin-right: 20px; 95 } 96 97 .wp-embed p { 98 margin: 0; 99 } 100 101 p.wp-embed-heading { 102 margin: 0 0 15px; 103 font-weight: bold; 104 font-size: 22px; 105 line-height: 1.3; 106 } 107 108 .wp-embed-heading a { 109 color: #32373c; 110 } 111 112 .wp-embed .wp-embed-more { 113 color: #b4b9be; 114 } 115 116 .wp-embed-footer { 117 display: table; 118 width: 100%; 119 margin-top: 30px; 120 } 121 122 .wp-embed-site-icon { 123 position: absolute; 124 top: 50%; 125 left: 0; 126 -webkit-transform: translateY(-50%); 127 -ms-transform: translateY(-50%); 128 transform: translateY(-50%); 129 height: 25px; 130 width: 25px; 131 border: 0; 132 } 133 134 .wp-embed-site-title { 135 font-weight: bold; 136 line-height: 25px; 137 } 138 139 .wp-embed-site-title a { 140 position: relative; 141 display: inline-block; 142 padding-left: 35px; 143 } 144 145 .wp-embed-site-title, 146 .wp-embed-meta { 147 display: table-cell; 148 } 149 150 .wp-embed-meta { 151 text-align: right; 152 white-space: nowrap; 153 vertical-align: middle; 154 } 155 156 .wp-embed-comments, 157 .wp-embed-share { 158 display: inline; 159 } 160 161 .wp-embed-meta a:hover { 162 text-decoration: none; 163 color: #0073aa; 164 } 165 166 .wp-embed-comments a { 167 line-height: 25px; 168 display: inline-block; 169 } 170 171 .wp-embed-comments + .wp-embed-share { 172 margin-left: 10px; 173 } 174 175 .wp-embed-share-dialog { 176 position: absolute; 177 top: 0; 178 left: 0; 179 right: 0; 180 bottom: 0; 181 background-color: rgba(10, 10, 10, 0.9); 182 color: #fff; 183 opacity: 1; 184 transition: opacity .25s ease-in-out; 185 -moz-transition: opacity .25s ease-in-out; 186 -webkit-transition: opacity .25s ease-in-out; 187 } 188 189 .wp-embed-share-dialog.hidden { 190 opacity: 0; 191 visibility: hidden; 192 } 193 194 .wp-embed-share-dialog-open, 195 .wp-embed-share-dialog-close { 196 margin: -8px 0 0; 197 padding: 0; 198 background: transparent; 199 border: none; 200 cursor: pointer; 201 outline: none; 202 } 203 204 .wp-embed-share-dialog-open .dashicons, 205 .wp-embed-share-dialog-close .dashicons { 206 padding: 4px; 207 } 208 209 .wp-embed-share-dialog-open .dashicons { 210 top: 8px; 211 } 212 213 .wp-embed-share-dialog-open:focus .dashicons, 214 .wp-embed-share-dialog-close:focus .dashicons { 215 -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); 216 box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); 217 -webkit-border-radius: 100%; 218 border-radius: 100%; 219 } 220 221 .wp-embed-share-dialog-close { 222 position: absolute; 223 top: 20px; 224 right: 20px; 225 font-size: 22px; 226 } 227 228 .wp-embed-share-dialog-close:hover { 229 text-decoration: none; 230 } 231 232 .wp-embed-share-dialog-close .dashicons { 233 height: 24px; 234 width: 24px; 235 -webkit-background-size: 24px 24px; 236 background-size: 24px; 237 } 238 239 .wp-embed-share-dialog-content { 240 height: 100%; 241 -webkit-transform-style: preserve-3d; 242 transform-style: preserve-3d; 243 overflow: hidden; 244 } 245 246 .wp-embed-share-dialog-text { 247 margin-top: 25px; 248 padding: 20px; 249 } 250 251 .wp-embed-share-tabs { 252 margin: 0 0 20px; 253 padding: 0; 254 list-style: none; 255 } 256 257 .wp-embed-share-tab-button { 258 display: inline; 259 } 260 261 .wp-embed-share-tab-button button { 262 margin: 0; 263 padding: 0; 264 border: none; 265 background: transparent; 266 font-size: 16px; 267 line-height: 1.3; 268 color: #aaa; 269 cursor: pointer; 270 -webkit-transition: color .1s ease-in; 271 transition: color .1s ease-in; 272 } 273 274 .wp-embed-share-tab-button [aria-selected="true"] { 275 color: #fff; 276 } 277 278 .wp-embed-share-tab-button button:hover { 279 color: #fff; 280 } 281 282 .wp-embed-share-tab-button + .wp-embed-share-tab-button { 283 margin: 0 0 0 10px; 284 padding: 0 0 0 11px; 285 border-left: 1px solid #aaa; 286 } 287 288 .wp-embed-share-tab[aria-hidden="true"] { 289 display: none; 290 } 291 292 p.wp-embed-share-description { 293 margin: 0; 294 font-size: 14px; 295 line-height: 1; 296 font-style: italic; 297 color: #aaa; 298 } 299 300 .wp-embed-share-input { 301 -webkit-box-sizing: border-box; 302 -moz-box-sizing: border-box; 303 box-sizing: border-box; 304 width: 100%; 305 border: none; 306 height: 28px; 307 margin: 0 0 10px 0; 308 padding: 0 5px; 309 font: 400 14px/1.5 'Open Sans', sans-serif; 310 resize: none; 311 cursor: text; 312 } 313 314 textarea.wp-embed-share-input { 315 height: 72px; 316 } 317 318 html[dir="rtl"] .wp-embed-featured-image.square { 319 float: right; 320 margin-right: 0; 321 322 margin-left: 20px; 323 } 324 325 html[dir="rtl"] .wp-embed-site-title a { 326 padding-left: 0; 327 padding-right: 35px; 328 } 329 330 html[dir="rtl"] .wp-embed-site-icon { 331 margin-right: 0; 332 margin-left: 10px; 333 left: auto; 334 right: 0; 335 } 336 337 html[dir="rtl"] .wp-embed-meta { 338 text-align: left; 339 } 340 341 html[dir="rtl"] .wp-embed-footer { 342 } 343 344 html[dir="rtl"] .wp-embed-share { 345 margin-left: 0; 346 margin-right: 10px; 347 } 348 349 html[dir="rtl"] .wp-embed-share-dialog-close { 350 right: auto; 351 left: 20px; 352 } 353 354 html[dir="rtl"] .wp-embed-share-tab-button + .wp-embed-share-tab-button { 355 margin: 0 10px 0 0; 356 padding: 0 11px 0 0; 357 border-left: none; 358 border-right: 1px solid #aaa; 359 } -
src/wp-includes/default-filters.php
422 422 add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 ); 423 423 add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 ); 424 424 425 // Embeds 426 427 add_action( 'parse_query', 'wp_oembed_parse_query' ); 428 429 add_action( 'wp_head', 'wp_oembed_add_discovery_links' ); 430 add_action( 'wp_head', 'wp_oembed_add_host_js' ); 431 432 add_action( 'oembed_head', 'print_emoji_detection_script' ); 433 add_action( 'oembed_head', 'print_emoji_styles' ); 434 add_action( 'oembed_head', 'print_oembed_embed_styles' ); 435 add_action( 'oembed_head', 'print_oembed_embed_scripts' ); 436 add_action( 'oembed_head', 'wp_print_head_scripts', 20 ); 437 add_action( 'oembed_head', 'wp_print_styles', 20 ); 438 add_action( 'oembed_head', 'wp_no_robots' ); 439 add_action( 'oembed_head', 'rel_canonical' ); 440 add_action( 'oembed_head', 'locale_stylesheet' ); 441 442 add_action( 'oembed_footer', 'wp_print_footer_scripts', 20 ); 443 444 add_filter( 'excerpt_more', 'wp_oembed_excerpt_more', 20 ); 445 add_filter( 'the_excerpt_embed', 'wptexturize' ); 446 add_filter( 'the_excerpt_embed', 'convert_chars' ); 447 add_filter( 'the_excerpt_embed', 'wpautop' ); 448 add_filter( 'the_excerpt_embed', 'shortcode_unautop' ); 449 add_filter( 'the_excerpt_embed', 'wp_oembed_excerpt_attachment' ); 450 451 add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 ); 452 add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 ); 453 425 454 unset( $filter, $action ); -
src/wp-includes/embed-functions.php
326 326 */ 327 327 return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr ); 328 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 if ( SCRIPT_DEBUG ) { 464 $output .= file_get_contents( ABSPATH . WPINC . '/js/wp-oembed.js' ); 465 } else { 466 /* 467 * If you're looking at a src version of this file, you'll see an "include" 468 * statement below. This is used by the `grunt build` process to directly 469 * include a minified version of wp-oembed.js, instead of using the 470 * file_get_contents() method from above. 471 * 472 * If you're looking at a build version of this file, you'll see a string of 473 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG 474 * and edit wp-oembed.js directly. 475 */ 476 $output .=<<<JS 477 include "js/wp-oembed.min.js" 478 JS; 479 } 480 $output .= "\n</script>"; 481 482 $output .= sprintf( 483 '<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>', 484 esc_url( $embed_url ), 485 absint( $width ), 486 absint( $height ), 487 esc_attr__( 'Embedded WordPress Post', 'oembed-api' ) 488 ); 489 490 /** 491 * Filters the oEmbed HTML output. 492 * 493 * @since 4.4.0 494 * 495 * @param string $output The default HTML. 496 * @param WP_Post $post Current post object. 497 * @param int $width Width of the response. 498 * @param int $height Height of the response. 499 */ 500 return apply_filters( 'oembed_html', $output, $post, $width, $height ); 501 } 502 503 /** 504 * Get the oEmbed response data for a given post. 505 * 506 * @since 4.4.0 507 * 508 * @param WP_Post|int $post Optional. Post object or ID. Default is global `$post`. 509 * @param int $width The requested width. 510 * @return array|false Response data on success, false if post doesn't exist. 511 */ 512 function get_oembed_response_data( $post = null, $width ) { 513 $post = get_post( $post ); 514 515 if ( ! $post ) { 516 return false; 517 } 518 519 if ( 'publish' !== get_post_status( $post ) ) { 520 return false; 521 } 522 523 /** 524 * Filter the allowed minimum width for the oEmbed response. 525 * 526 * @param int $width The minimum width. Defaults to 200. 527 */ 528 $minwidth = apply_filters( 'oembed_minwidth', 200 ); 529 530 /** 531 * Filter the allowed maximum width for the oEmbed response. 532 * 533 * @param int $width The maximum width. Defaults to 600. 534 */ 535 $maxwidth = apply_filters( 'oembed_maxwidth', 600 ); 536 537 if ( $width < $minwidth ) { 538 $width = $minwidth; 539 } else if ( $width > $maxwidth ) { 540 $width = $maxwidth; 541 } 542 543 $height = ceil( $width / 16 * 9 ); 544 545 if ( 200 > $height ) { 546 $height = 200; 547 } 548 549 $data = array( 550 'version' => '1.0', 551 'provider_name' => get_bloginfo( 'name' ), 552 'provider_url' => get_home_url(), 553 'author_name' => get_bloginfo( 'name' ), 554 'author_url' => get_home_url(), 555 'title' => $post->post_title, 556 'type' => 'link', 557 ); 558 559 $author = get_userdata( $post->post_author ); 560 561 if ( $author ) { 562 $data['author_name'] = $author->display_name; 563 $data['author_url'] = get_author_posts_url( $author->ID ); 564 } 565 566 /** 567 * Filter the oEmbed response data. 568 * 569 * @since 4.4.0 570 * 571 * @param array $data The response data. 572 * @param WP_Post $post The post object. 573 * @param int $width The requested width. 574 * @param int $height The calculated height. 575 */ 576 return apply_filters( 'oembed_response_data', $data, $post, $width, $height ); 577 } 578 579 /** 580 * Filters the oEmbed response data to return an iframe embed code. 581 * 582 * @since 4.4.0 583 * 584 * @param array $data The response data. 585 * @param WP_Post $post The post object. 586 * @param int $width The requested width. 587 * @param int $height The calculated height. 588 * @return array The modified response data. 589 */ 590 function get_oembed_response_data_rich( $data, $post, $width, $height ) { 591 $data['width'] = absint( $width ); 592 $data['height'] = absint( $height ); 593 $data['type'] = 'rich'; 594 $data['html'] = get_post_embed_html( $post, $width, $height ); 595 596 // Add post thumbnail to response if available. 597 $thumbnail_id = false; 598 599 if ( has_post_thumbnail( $post->ID ) ) { 600 $thumbnail_id = get_post_thumbnail_id( $post->ID ); 601 } 602 603 if ( 'attachment' === get_post_type( $post ) ) { 604 if ( wp_attachment_is_image( $post ) ) { 605 $thumbnail_id = $post->ID; 606 } else if ( wp_attachment_is( 'video', $post ) ) { 607 $thumbnail_id = get_post_thumbnail_id( $post ); 608 $data['type'] = 'video'; 609 } 610 } 611 612 if ( $thumbnail_id ) { 613 list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) ); 614 $data['thumbnail_url'] = $thumbnail_url; 615 $data['thumbnail_width'] = $thumbnail_width; 616 $data['thumbnail_height'] = $thumbnail_height; 617 } 618 619 return $data; 620 } 621 622 /** 623 * Ensures that the specified format is either 'json' or 'xml'. 624 * 625 * @since 4.4.0 626 * 627 * @param string $format The oEmbed response format. Accepts 'json', 'xml'. 628 * @return string The format, either 'xml' or 'json'. Default 'json'. 629 */ 630 function wp_oembed_ensure_format( $format ) { 631 if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) { 632 return 'json'; 633 } 634 635 return $format; 636 } 637 638 /** 639 * Creates an XML string from a given array. 640 * 641 * @since 4.4.0 642 * @access private 643 * 644 * @param array $data The original oEmbed response data. 645 * @param SimpleXMLElement $node Optional. XML node to append the result to recursively. 646 * @return string|false XML string on success, false on error. 647 */ 648 function _oembed_create_xml( $data, $node = null ) { 649 if ( ! is_array( $data ) || empty( $data ) ) { 650 return false; 651 } 652 653 if ( null === $node ) { 654 $node = new SimpleXMLElement( '<oembed></oembed>' ); 655 } 656 657 foreach ( $data as $key => $value ) { 658 if ( is_numeric( $key ) ) { 659 $key = 'oembed'; 660 } 661 662 if ( is_array( $value ) ) { 663 $item = $node->addChild( $key ); 664 _oembed_create_xml( $value, $item ); 665 } else { 666 $node->addChild( $key, esc_html( $value ) ); 667 } 668 } 669 670 return $node->asXML(); 671 } 672 673 /** 674 * Filters the returned oEmbed HTML. 675 * 676 * If the $url isn't on the trusted providers list, 677 * we need to filter the HTML heavily for security. 678 * 679 * Only filters 'rich' and 'html' response types. 680 * 681 * @since 4.4.0 682 * 683 * @param string $return The returned oEmbed HTML. 684 * @param object $data A data object result from an oEmbed provider. 685 * @param string $url The URL of the content to be embedded. 686 * @return string The filtered and sanitized oEmbed result. 687 */ 688 function wp_filter_oembed_result( $return, $data, $url ) { 689 if ( false === $return || ! in_array( $data->type, array( 'rich', 'video' ) ) ) { 690 return $return; 691 } 692 693 require_once( ABSPATH . WPINC . '/class-oembed.php' ); 694 $wp_oembed = _wp_oembed_get_object(); 695 696 // Don't modify the HTML for trusted providers. 697 if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) { 698 return $return; 699 } 700 701 $allowed_html = array( 702 'iframe' => array( 703 'src' => true, 704 'width' => true, 705 'height' => true, 706 'frameborder' => true, 707 'marginwidth' => true, 708 'marginheight' => true, 709 'scrolling' => true, 710 'title' => true, 711 'class' => true, 712 ), 713 ); 714 715 $html = wp_kses( $return, $allowed_html ); 716 preg_match( '|^.*(<iframe.*?></iframe>).*$|m', $html, $iframes ); 717 718 if ( empty( $iframes ) ) { 719 return false; 720 } 721 722 $html = str_replace( '<iframe', '<iframe sandbox="allow-scripts" security="restricted"', $iframes[1] ); 723 724 preg_match( '/ src=[\'"]([^\'"]*)[\'"]/', $html, $results ); 725 726 if ( ! empty( $results ) ) { 727 $secret = wp_generate_password( 10, false ); 728 729 $url = esc_url( "{$results[1]}#?secret=$secret" ); 730 731 $html = str_replace( $results[0], " src=\"$url\" data-secret=\"$secret\"", $html ); 732 } 733 734 return $html; 735 } 736 737 /** 738 * Filters the string in the "more" link displayed after a trimmed excerpt. 739 * 740 * @since 4.4.0 741 * 742 * @param string $more_string The string shown within the more link. 743 * @return string The modified excerpt. 744 */ 745 function wp_oembed_excerpt_more( $more_string ) { 746 if ( ! is_embed() ) { 747 return $more_string; 748 } 749 750 return sprintf( 751 _x( '… %s', 'read more link', 'oembed-api' ), 752 sprintf( 753 '<a class="wp-embed-more" href="%s" target="_top">%s</a>', 754 get_the_permalink(), 755 __( 'Read more', 'oembed-api' ) 756 ) 757 ); 758 } 759 760 /** 761 * Display the post excerpt for the embed template. 762 * 763 * @since 4.4.0 764 */ 765 function the_excerpt_embed() { 766 $output = get_the_excerpt(); 767 768 /** 769 * Filter the post excerpt for the embed template. 770 * 771 * @param string $output The current post excerpt. 772 */ 773 echo apply_filters( 'the_excerpt_embed', $output ); 774 } 775 776 /** 777 * Filters the post excerpt for the embed template. 778 * 779 * Shows players for video and audio attachments. 780 * 781 * @since 4.4.0 782 * 783 * @param string $content The current post excerpt. 784 * @return string The modified post excerpt. 785 */ 786 function wp_oembed_excerpt_attachment( $content ) { 787 if ( is_attachment() ) { 788 return prepend_attachment( '' ); 789 } 790 791 return $content; 792 } 793 794 /** 795 * Print the CSS in the embed iframe header. 796 * 797 * @since 4.4.0 798 */ 799 function print_oembed_embed_styles() { 800 ?> 801 <style type="text/css"> 802 <?php 803 if ( WP_DEBUG ) { 804 readfile( ABSPATH . WPINC . "/css/wp-oembed-embed.css" ); 805 } else { 806 /* 807 * If you're looking at a src version of this file, you'll see an "include" 808 * statement below. This is used by the `grunt build` process to directly 809 * include a minified version of wp-oembed-embed.css, instead of using the 810 * readfile() method from above. 811 * 812 * If you're looking at a build version of this file, you'll see a string of 813 * minified CSS. If you need to debug it, please turn on WP_DEBUG 814 * and edit wp-oembed-embed.css directly. 815 */ 816 ?> 817 include "css/wp-oembed-embed.min.css" 818 <?php 819 } 820 ?> 821 </style> 822 <?php 823 } 824 825 /** 826 * Print the CSS in the embed iframe header. 827 * 828 * @since 4.4.0 829 */ 830 function print_oembed_embed_scripts() { 831 ?> 832 <script type="text/javascript"> 833 <?php 834 if ( SCRIPT_DEBUG ) { 835 readfile( ABSPATH . WPINC . "/js/wp-oembed-embed.js" ); 836 } else { 837 /* 838 * If you're looking at a src version of this file, you'll see an "include" 839 * statement below. This is used by the `grunt build` process to directly 840 * include a minified version of wp-oembed-embed.js, instead of using the 841 * readfile() method from above. 842 * 843 * If you're looking at a build version of this file, you'll see a string of 844 * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG 845 * and edit wp-oembed-embed.js directly. 846 */ 847 ?> 848 include "js/wp-oembed-embed.min.js" 849 <?php 850 } 851 ?> 852 </script> 853 <?php 854 } 855 No newline at end of file -
src/wp-includes/embed-template.php
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 <?php 26 /** 27 * Print scripts or data in the embed template <head> tag. 28 * 29 * @since 4.4.0 30 */ 31 do_action( 'oembed_head' ); 32 ?> 33 </head> 34 <body <?php body_class(); ?>> 35 <?php 36 if ( have_posts() ) : 37 while ( have_posts() ) : the_post(); 38 // Add post thumbnail to response if available. 39 $thumbnail_id = false; 40 41 if ( has_post_thumbnail() ) { 42 $thumbnail_id = get_post_thumbnail_id(); 43 } 44 45 if ( 'attachment' === get_post_type() && wp_attachment_is_image() ) { 46 $thumbnail_id = get_the_ID(); 47 } 48 49 if ( $thumbnail_id ) { 50 $aspect_ratio = 1; 51 $measurements = array( 1, 1 ); 52 $image_size = 'full'; // Fallback. 53 54 $meta = wp_get_attachment_metadata( $thumbnail_id ); 55 if ( is_array( $meta ) ) { 56 foreach ( $meta['sizes'] as $size => $data ) { 57 if ( $data['width'] / $data['height'] > $aspect_ratio ) { 58 $aspect_ratio = $data['width'] / $data['height']; 59 $measurements = array( $data['width'], $data['height'] ); 60 $image_size = $size; 61 } 62 } 63 } 64 65 /** 66 * Filter the thumbnail image size for use in the embed template. 67 * 68 * @param string $image_size Thumbnail image size. 69 */ 70 $image_size = apply_filters( 'oembed_thumbnail_image_size', $image_size ); 71 72 $shape = $measurements[0] / $measurements[1] >= 1.75 ? 'rectangular' : 'square'; 73 74 /** 75 * Filter the thumbnail shape for use in the embed template. 76 * 77 * Rectangular images are shown above the title 78 * while square images are shown next to the content. 79 * 80 * @since 4.4.0 81 * 82 * @param string $shape Thumbnail image shape. Either 'rectangular' or 'square'. 83 */ 84 $shape = apply_filters( 'oembed_thumbnail_image_shape', $shape ); 85 } 86 ?> 87 <div <?php post_class( 'wp-embed' ); ?>> 88 <?php if ( $thumbnail_id && 'rectangular' === $shape ) : ?> 89 <div class="wp-embed-featured-image rectangular"> 90 <a href="<?php the_permalink(); ?>" target="_top"> 91 <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?> 92 </a> 93 </div> 94 <?php endif; ?> 95 96 <p class="wp-embed-heading"> 97 <a href="<?php the_permalink(); ?>" target="_top"> 98 <?php the_title(); ?> 99 </a> 100 </p> 101 102 <?php if ( $thumbnail_id && 'square' === $shape ) : ?> 103 <div class="wp-embed-featured-image square"> 104 <a href="<?php the_permalink(); ?>" target="_top"> 105 <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?> 106 </a> 107 </div> 108 <?php endif; ?> 109 110 <div class="wp-embed-excerpt"><?php the_excerpt_embed(); ?></div> 111 112 <?php 113 /** 114 * Print additional content after the embed excerpt. 115 * 116 * @since 4.4.0 117 */ 118 do_action( 'oembed_content' ); 119 ?> 120 121 <div class="wp-embed-footer"> 122 <div class="wp-embed-site-title"> 123 <?php 124 $site_icon_url = admin_url( 'images/w-logo-blue.png' ); 125 126 if ( function_exists( 'get_site_icon_url' ) ) { 127 $site_icon_url = get_site_icon_url( 32, $site_icon_url ); 128 } 129 130 /** 131 * Filters the site icon URL for use in the embed template. 132 * 133 * @param string $site_icon_url The site icon URL. 134 */ 135 $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url ); 136 137 printf( 138 '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>', 139 esc_url( home_url() ), 140 esc_url( $site_icon_url ), 141 esc_attr( get_bloginfo( 'name' ) ) 142 ); 143 ?> 144 </div> 145 146 <div class="wp-embed-meta"> 147 <?php 148 /** 149 * Print additional meta content in the embed template. 150 * 151 * @since 4.4.0 152 */ 153 do_action( 'oembed_content_meta'); 154 ?> 155 <?php if ( get_comments_number() || comments_open() ) : ?> 156 <div class="wp-embed-comments"> 157 <a href="<?php comments_link(); ?>" target="_top"> 158 <span class="dashicons dashicons-admin-comments"></span> 159 <?php 160 printf( 161 _n( 162 '%s <span class="screen-reader-text">Comment</span>', 163 '%s <span class="screen-reader-text">Comments</span>', 164 get_comments_number(), 165 'oembed-api' 166 ), 167 absint( get_comments_number() ) 168 ); 169 ?> 170 </a> 171 </div> 172 <?php endif; ?> 173 <div class="wp-embed-share"> 174 <button type="button" class="wp-embed-share-dialog-open" 175 aria-label="<?php esc_attr_e( 'Open sharing dialog', 'oembed-api' ); ?>"> 176 <span class="dashicons dashicons-share"></span> 177 </button> 178 </div> 179 </div> 180 </div> 181 <div class="wp-embed-share-dialog hidden"> 182 <div class="wp-embed-share-dialog-content"> 183 <div class="wp-embed-share-dialog-text"> 184 <ul class="wp-embed-share-tabs" role="tablist"> 185 <li id="wp-embed-share-tab-button-wordpress" class="wp-embed-share-tab-button" role="presentation"> 186 <button role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed', 'oembed-api' ); ?></button> 187 </li> 188 <li id="wp-embed-share-tab-button-embed" class="wp-embed-share-tab-button" role="presentation"> 189 <button role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed', 'oembed-api' ); ?></button> 190 </li> 191 </ul> 192 <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"> 193 <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" tabindex="0" readonly/> 194 195 <p class="wp-embed-share-description"> 196 <?php _e( 'Copy and paste this URL into your WordPress site to embed', 'oembed-api' ); ?> 197 </p> 198 </div> 199 <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"> 200 <textarea class="wp-embed-share-input" tabindex="0" readonly><?php echo esc_attr( get_post_embed_html( null, 600, 400 ) ); ?></textarea> 201 202 <p class="wp-embed-share-description"> 203 <?php _e( 'Copy and paste this code into your site to embed', 'oembed-api' ); ?> 204 </p> 205 </div> 206 </div> 207 208 <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog', 'oembed-api' ); ?>"> 209 <span class="dashicons dashicons-no"></span> 210 </button> 211 </div> 212 </div> 213 </div> 214 <?php 215 endwhile; 216 else : 217 ?> 218 <div class="wp-embed"> 219 <p class="wp-embed-heading"><?php _e( 'Page not found', 'oembed-api' ); ?></p> 220 221 <div class="wp-embed-excerpt"> 222 <p><?php _e( 'Error 404! The requested content was not found.', 'oembed-api' ) ?></p> 223 </div> 224 225 <div class="wp-embed-footer"> 226 <div class="wp-embed-site-title"> 227 <?php 228 $site_icon_url = admin_url( 'images/w-logo-blue.png' ); 229 230 if ( function_exists( 'get_site_icon_url' ) ) { 231 $site_icon_url = get_site_icon_url( 32, $site_icon_url ); 232 } 233 234 /** 235 * Filters the site icon URL for use in the embed template. 236 * 237 * @param string $site_icon_url The site icon URL. 238 */ 239 $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url ); 240 241 printf( 242 '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>', 243 esc_url( home_url() ), 244 esc_url( $site_icon_url ), 245 esc_attr( get_bloginfo( 'name' ) ) 246 ); 247 ?> 248 </div> 249 </div> 250 </div> 251 <?php 252 endif; 253 254 /** 255 * Print scripts or data before the closing body tag in the embed template. 256 * 257 * @since 4.4.0 258 */ 259 do_action( 'oembed_footer' ); 260 ?> 261 </body> 262 </html> -
src/wp-includes/js/tinymce/plugins/wpoembed/plugin.js
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 ); -
src/wp-includes/js/wp-oembed-embed.js
1 (function ( window, document ) { 2 'use strict'; 3 4 var secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' ), 5 resizing; 6 7 function sendEmbedMessage( message, value ) { 8 window.parent.postMessage( { 9 message: message, 10 value: value, 11 secret: secret 12 }, '*' ); 13 } 14 15 function onLoad() { 16 var share_dialog = document.querySelector( '.wp-embed-share-dialog' ), 17 share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ), 18 share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ), 19 share_input = document.querySelectorAll( '.wp-embed-share-input' ), 20 share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ), 21 links = document.getElementsByTagName( 'a' ), 22 i; 23 24 if ( share_input ) { 25 for ( i = 0; i < share_input.length; i++ ) { 26 share_input[ i ].addEventListener( 'click', function ( e ) { 27 e.target.select(); 28 } ); 29 } 30 } 31 32 function openSharingDialog() { 33 share_dialog.className = share_dialog.className.replace( 'hidden', '' ); 34 share_input[ 0 ].select(); 35 } 36 37 function closeSharingDialog() { 38 share_dialog.className += ' hidden'; 39 document.querySelector( '.wp-embed-share-dialog-open' ).focus(); 40 } 41 42 if ( share_dialog_open ) { 43 share_dialog_open.addEventListener( 'click', function ( e ) { 44 openSharingDialog(); 45 e.preventDefault(); 46 } ); 47 } 48 49 if ( share_dialog_close ) { 50 share_dialog_close.addEventListener( 'click', function ( e ) { 51 closeSharingDialog(); 52 e.preventDefault(); 53 } ); 54 } 55 56 function shareClickHandler( e ) { 57 var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); 58 currentTab.setAttribute( 'aria-selected', 'false' ); 59 document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 60 61 e.target.setAttribute( 'aria-selected', 'true' ); 62 document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 63 } 64 65 function shareKeyHandler( e ) { 66 var target = e.target, 67 previousSibling = target.parentElement.previousElementSibling, 68 nextSibling = target.parentElement.nextElementSibling, 69 newTab, newTabChild; 70 71 if ( 37 === e.keyCode ) { 72 newTab = previousSibling; 73 } else if ( 39 === e.keyCode ) { 74 newTab = nextSibling; 75 } else { 76 return false; 77 } 78 79 if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) { 80 newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling; 81 } 82 83 if ( newTab ) { 84 newTabChild = newTab.firstElementChild; 85 86 target.setAttribute( 'tabindex', '-1' ); 87 target.setAttribute( 'aria-selected', false ); 88 document.querySelector( '#' + target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 89 90 newTabChild.setAttribute( 'tabindex', '0' ); 91 newTabChild.setAttribute( 'aria-selected', 'true' ); 92 newTabChild.focus(); 93 document.querySelector( '#' + newTabChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 94 } 95 } 96 97 if ( share_dialog_tabs ) { 98 for ( i = 0; i < share_dialog_tabs.length; i++ ) { 99 share_dialog_tabs[ i ].addEventListener( 'click', shareClickHandler ); 100 101 share_dialog_tabs[ i ].addEventListener( 'keydown', shareKeyHandler ); 102 } 103 } 104 105 document.addEventListener( 'keydown', function ( e ) { 106 if ( e.keyCode === 27 && -1 === share_dialog.className.indexOf( 'hidden' ) ) { 107 closeSharingDialog(); 108 } 109 }, false ); 110 111 if ( window.self === window.top ) { 112 return; 113 } 114 115 /** 116 * Send this document's height to the parent (embedding) site. 117 */ 118 sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); 119 120 /** 121 * Detect clicks to external (_top) links. 122 */ 123 function linkClickHandler( e ) { 124 var target = e.target, 125 href; 126 if ( target.hasAttribute( 'href' ) ) { 127 href = target.getAttribute( 'href' ); 128 } else { 129 href = target.parentElement.getAttribute( 'href' ); 130 } 131 132 /** 133 * Send link target to the parent (embedding) site. 134 */ 135 sendEmbedMessage( 'link', href ); 136 e.preventDefault(); 137 } 138 139 for ( i = 0; i < links.length; i++ ) { 140 links[ i ].addEventListener( 'click', linkClickHandler ); 141 } 142 } 143 144 document.addEventListener( 'DOMContentLoaded', onLoad, false ); 145 146 /** 147 * Iframe resize handler. 148 */ 149 function onResize() { 150 if ( window.self === window.top ) { 151 return; 152 } 153 154 clearTimeout( resizing ); 155 156 resizing = setTimeout( function () { 157 sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); 158 }, 100 ); 159 } 160 161 window.addEventListener( 'resize', onResize, false ); 162 })( window, document ); -
src/wp-includes/js/wp-oembed.js
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 var data = e.data; 12 if ( ! ( data.secret || data.message || data.value ) ) { 13 return; 14 } 15 16 var iframes = document.querySelectorAll( '.wp-embedded-content[data-secret="' + data.secret + '"]' ); 17 18 for ( var i = 0; i < iframes.length; i++ ) { 19 var source = iframes[ i ]; 20 21 /* Resize the iframe on request. */ 22 if ( 'height' === data.message ) { 23 var height = data.value; 24 if ( height > 1000 ) { 25 height = 1000; 26 } else if ( height < 200 ) { 27 height = 200; 28 } 29 30 source.height = (height) + 'px'; 31 } 32 33 /* Link to a specific URL on request. */ 34 if ( 'link' === data.message ) { 35 var sourceURL = document.createElement( 'a' ), targetURL = document.createElement( 'a' ); 36 sourceURL.href = source.getAttribute( 'src' ); 37 targetURL.href = data.value; 38 39 /* Only continue if link hostname matches iframe's hostname. */ 40 if ( targetURL.host === sourceURL.host && document.activeElement === source ) { 41 window.top.location.href = data.value; 42 } 43 } 44 } 45 }; 46 47 window.addEventListener( 'message', window.wp.receiveEmbedMessage, false ); 48 49 function onLoad() { 50 var isIE10 = -1 !== navigator.appVersion.indexOf( 'MSIE 10' ), 51 isIE11 = !!navigator.userAgent.match( /Trident.*rv\:11\./ ); 52 53 /* Remove security attribute from iframes in IE10 and IE11. */ 54 if ( isIE10 || isIE11 ) { 55 var iframes = document.querySelectorAll( '.wp-embedded-content[security]' ), iframeClone; 56 57 for ( var i = 0; i < iframes.length; i++ ) { 58 iframeClone = iframes[ i ].cloneNode( true ); 59 iframeClone.removeAttribute( 'security' ); 60 iframes[ i ].parentNode.insertBefore( iframeClone, iframes[ i ].nextSibling ); 61 iframes[ i ].parentNode.removeChild( iframes[ i ] ); 62 } 63 } 64 } 65 66 document.addEventListener( 'DOMContentLoaded', onLoad, false ); 67 })( window, document ); -
src/wp-includes/query.php
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 … … 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 … … 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 … … 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 … … 4935 4977 $link = user_trailingslashit( trailingslashit( $link ) . 'feed' ); 4936 4978 } elseif ( isset( $GLOBALS['wp_query']->query_vars['paged'] ) && $GLOBALS['wp_query']->query_vars['paged'] > 1 ) { 4937 4979 $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . $GLOBALS['wp_query']->query_vars['paged'] ); 4980 } elseif( is_embed() ) { 4981 $link = user_trailingslashit( trailingslashit( $link ) . 'embed' ); 4938 4982 } elseif ( is_404() ) { 4939 4983 // Add rewrite endpoints if necessary. 4940 4984 foreach ( $wp_rewrite->endpoints as $endpoint ) { -
src/wp-includes/script-loader.php
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
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
147 147 require( ABSPATH . WPINC . '/shortcodes.php' ); 148 148 require( ABSPATH . WPINC . '/class-wp-embed.php' ); 149 149 require( ABSPATH . WPINC . '/embed-functions.php' ); 150 require( ABSPATH . WPINC . '/class-wp-oembed-controller.php' ); 150 151 require( ABSPATH . WPINC . '/media.php' ); 151 152 require( ABSPATH . WPINC . '/http.php' ); 152 153 require( ABSPATH . WPINC . '/widgets.php' ); -
tests/phpunit/tests/oembed/controller.php
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 } -
tests/phpunit/tests/oembed/discovery.php
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 } -
tests/phpunit/tests/oembed/filterResult.php
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 } -
tests/phpunit/tests/oembed/getResponseData.php
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_maxwidth_invalid() { 127 $post = $this->factory->post->create_and_get(); 128 129 $data = get_oembed_response_data( $post, '400;" DROP TABLES' ); 130 131 $this->assertEquals( 400, $data['width'] ); 132 $this->assertEquals( 225, $data['height'] ); 133 134 $data = get_oembed_response_data( $post, "lol this isn't even a number?!?!?" ); 135 136 $this->assertEquals( 200, $data['width'] ); 137 $this->assertEquals( 200, $data['height'] ); 138 } 139 140 function test_get_oembed_response_data_with_thumbnail() { 141 $post = $this->factory->post->create_and_get(); 142 $file = DIR_TESTDATA . '/images/canola.jpg'; 143 $attachment_id = $this->factory->attachment->create_object( $file, $post->ID, array( 144 'post_mime_type' => 'image/jpeg', 145 ) ); 146 set_post_thumbnail( $post, $attachment_id ); 147 148 $data = get_oembed_response_data( $post, 400 ); 149 150 $this->assertArrayHasKey( 'thumbnail_url', $data ); 151 $this->assertArrayHasKey( 'thumbnail_width', $data ); 152 $this->assertArrayHasKey( 'thumbnail_height', $data ); 153 $this->assertTrue( 400 >= $data['thumbnail_width'] ); 154 } 155 156 function test_get_oembed_response_data_for_attachment() { 157 $parent = $this->factory->post->create(); 158 $file = DIR_TESTDATA . '/images/canola.jpg'; 159 $post = $this->factory->attachment->create_object( $file, $parent, array( 160 'post_mime_type' => 'image/jpeg', 161 ) ); 162 163 $data = get_oembed_response_data( $post, 400 ); 164 165 $this->assertArrayHasKey( 'thumbnail_url', $data ); 166 $this->assertArrayHasKey( 'thumbnail_width', $data ); 167 $this->assertArrayHasKey( 'thumbnail_height', $data ); 168 $this->assertTrue( 400 >= $data['thumbnail_width'] ); 169 } 170 } -
tests/phpunit/tests/oembed/headers.php
1 <?php 2 3 /** 4 * @runTestsInSeparateProcesses 5 * @preserveGlobalState disabled 6 * @group oembed 7 */ 8 class Tests_oEmbed_HTTP_Headers extends WP_UnitTestCase { 9 function test_request_json_response_headers() { 10 if ( ! function_exists( 'xdebug_get_headers' ) ) { 11 $this->markTestSkipped( 'xdebug is required for this test' ); 12 } 13 14 $post = $this->factory->post->create_and_get( array( 15 'post_title' => 'Hello World', 16 ) ); 17 18 $request = array( 19 'url' => get_permalink( $post->ID ), 20 'format' => 'json', 21 'maxwidth' => 600, 22 'callback' => '', 23 ); 24 25 $legacy_controller = new WP_oEmbed_Controller(); 26 $legacy_controller->dispatch( $request ); 27 28 $headers = xdebug_get_headers(); 29 30 $this->assertTrue( in_array( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ), $headers ) ); 31 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) ); 32 33 $request['callback'] = 'foobar'; 34 35 $legacy_controller->dispatch( $request ); 36 37 $headers = xdebug_get_headers(); 38 39 $this->assertTrue( in_array( 'Content-Type: application/javascript; charset=' . get_option( 'blog_charset' ), $headers ) ); 40 $this->assertTrue( in_array( 'X-Content-Type-Options: nosniff', $headers ) ); 41 } 42 43 function test_request_xml_response_headers() { 44 if ( ! function_exists( 'xdebug_get_headers' ) ) { 45 $this->markTestSkipped( 'xdebug is required for this test' ); 46 } 47 48 $post = $this->factory->post->create_and_get( array( 49 'post_title' => 'Hello World', 50 ) ); 51 52 $request = array( 53 'url' => get_permalink( $post->ID ), 54 'format' => 'xml', 55 'maxwidth' => 600, 56 ); 57 58 $legacy_controller = new WP_oEmbed_Controller(); 59 $legacy_controller->dispatch( $request ); 60 61 $headers = xdebug_get_headers(); 62 63 $this->assertTrue( in_array( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), $headers ) ); 64 } 65 } -
tests/phpunit/tests/oembed/postEmbedUrl.php
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 } -
tests/phpunit/tests/oembed/template.php
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 }