diff --git a/wp-includes/admin-bar.php b/wp-includes/admin-bar.php
index a12e9c9e71..696c369978 100644
--- a/wp-includes/admin-bar.php
+++ b/wp-includes/admin-bar.php
@@ -898,6 +898,10 @@ function is_admin_bar_showing() {
if ( defined('XMLRPC_REQUEST') || defined('DOING_AJAX') || defined('IFRAME_REQUEST') )
return false;
+ if ( is_embed() ) {
+ return false;
+ }
+
// Integrated into the admin.
if ( is_admin() )
return true;
diff --git a/wp-includes/class-wp-editor.php b/wp-includes/class-wp-editor.php
index 911aaab540..8a6dc3bd02 100644
--- a/wp-includes/class-wp-editor.php
+++ b/wp-includes/class-wp-editor.php
@@ -401,7 +401,8 @@ final class _WP_Editors {
'wplink',
'wpdialogs',
'wptextpattern',
- 'wpview'
+ 'wpview',
+ 'wpoembed',
);
if ( ! self::$has_medialib ) {
diff --git a/wp-includes/class-wp-embed.php b/wp-includes/class-wp-embed.php
index d4b1ded4f0..730fc4fc91 100644
--- a/wp-includes/class-wp-embed.php
+++ b/wp-includes/class-wp-embed.php
@@ -233,12 +233,13 @@ class WP_Embed {
* Filter whether to inspect the given URL for discoverable link tags.
*
* @since 2.9.0
+ * @since 4.4.0 The default value changed to true.
*
* @see WP_oEmbed::discover()
*
- * @param bool $enable Whether to enable `` tag discovery. Default false.
+ * @param bool $enable Whether to enable `` tag discovery. Default true.
*/
- $attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html' ) );
+ $attr['discover'] = ( apply_filters( 'embed_oembed_discover', true ) );
// Use oEmbed to get the HTML
$html = wp_oembed_get( $url, $attr );
diff --git a/wp-includes/class-wp-oembed-controller.php b/wp-includes/class-wp-oembed-controller.php
new file mode 100644
index 0000000000..0fc25ba817
--- /dev/null
+++ b/wp-includes/class-wp-oembed-controller.php
@@ -0,0 +1,159 @@
+get( 'oembed', false ) ) {
+ return;
+ }
+
+ if ( false === $wp_query->get( 'url', false ) ) {
+ status_header( 400 );
+ echo 'URL parameter missing';
+ exit;
+ }
+
+ $url = esc_url_raw( get_query_var( 'url' ) );
+
+ $format = wp_oembed_ensure_format( get_query_var( 'format' ) );
+
+ /**
+ * Filter the maxwidth oEmbed parameter.
+ *
+ * @since 4.4.0
+ *
+ * @param int $maxwidth Maximum allowed width. Default 600.
+ */
+ $maxwidth = apply_filters( 'oembed_default_width', 600 );
+ $maxwidth = absint( get_query_var( 'maxwidth', $maxwidth ) );
+
+ $callback = get_query_var( '_jsonp', false );
+
+ $request = array(
+ 'url' => $url,
+ 'format' => $format,
+ 'maxwidth' => $maxwidth,
+ 'callback' => $callback,
+ );
+
+ echo $this->dispatch( $request );
+ exit;
+ }
+
+ /**
+ * Handle the whole request and print the response.
+ *
+ * @since 4.4.0
+ *
+ * @param array $request The request arguments.
+ * @return string The oEmbed API response.
+ */
+ public function dispatch( $request ) {
+ $post_id = url_to_postid( $request['url'] );
+
+ /**
+ * Filter the determined post id.
+ *
+ * @since 4.4.0
+ *
+ * @param int $post_id The post ID.
+ * @param string $url The requestd URL.
+ */
+ $post_id = apply_filters( 'oembed_request_post_id', $post_id, $request['url'] );
+
+ $data = get_oembed_response_data( $post_id, $request['maxwidth'] );
+
+ if ( false === $data ) {
+ status_header( 404 );
+ return __( 'Invalid URL.', 'oembed-api' );
+ }
+
+ if ( 'json' === $request['format'] ) {
+ return $this->json_response( $data, $request );
+ }
+
+ return $this->xml_response( $data );
+ }
+
+ /**
+ * Print the oEmbed JSON response.
+ *
+ * @since 4.4.0
+ *
+ * @param array $data The oEmbed response data.
+ * @param array $request The request arguments.
+ * @return string The JSON response data.
+ */
+ public function json_response( $data, $request ) {
+ if ( ! is_string( $request['callback'] ) || preg_match( '/[^\w\.]/', $request['callback'] ) ) {
+ $request['callback'] = false;
+ }
+
+ $result = wp_json_encode( $data );
+
+ // Bail if the result couldn't be JSON encoded.
+ if ( ! $result || ! is_array( $data ) || empty( $data ) ) {
+ status_header( 501 );
+ return 'Not implemented';
+ }
+
+ if ( ! headers_sent() ) {
+ $content_type = $request['callback'] ? 'application/javascript' : 'application/json';
+ header( 'Content-Type: ' . $content_type . '; charset=' . get_option( 'blog_charset' ) );
+ header( 'X-Content-Type-Options: nosniff' );
+ }
+
+ if ( $request['callback'] ) {
+ return '/**/' . $request['callback'] . '(' . $result . ')';
+ }
+
+ return $result;
+ }
+
+ /**
+ * Print the oEmbed XML response.
+ *
+ * @since 4.4.0
+ *
+ * @param array $data The oEmbed response data.
+ * @return string The XML response data.
+ */
+ public function xml_response( $data ) {
+ $result = _oembed_create_xml( $data );
+
+ // Bail if there's no XML.
+ if ( ! $result ) {
+ status_header( 501 );
+ return 'Not implemented';
+ }
+
+ if ( ! headers_sent() ) {
+ header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ) );
+ }
+
+ return $result;
+ }
+}
diff --git a/wp-includes/class-wp-rewrite.php b/wp-includes/class-wp-rewrite.php
index 84a57c8107..b7b3753dd4 100644
--- a/wp-includes/class-wp-rewrite.php
+++ b/wp-includes/class-wp-rewrite.php
@@ -861,6 +861,7 @@ class WP_Rewrite {
$trackbackregex = 'trackback/?$';
$pageregex = $this->pagination_base . '/?([0-9]{1,})/?$';
$commentregex = $this->comments_pagination_base . '-([0-9]{1,})/?$';
+ $embedregex = 'embed/?$';
//build up an array of endpoint regexes to append => queries to append
if ( $endpoints ) {
@@ -884,6 +885,8 @@ class WP_Rewrite {
$index = $this->index; //probably 'index.php'
$feedindex = $index;
$trackbackindex = $index;
+ $embedindex = $index;
+
//build a list from the rewritecode and queryreplace arrays, that will look something like
//tagname=$matches[i] where i is the current $i
$queries = array();
@@ -1029,8 +1032,14 @@ class WP_Rewrite {
//create query and regex for trackback
$trackbackmatch = $match . $trackbackregex;
$trackbackquery = $trackbackindex . '?' . $query . '&tb=1';
+
+ // Create query and regex for embeds.
+ $embedmatch = $match . $embedregex;
+ $embedquery = $embedindex . '?' . $query . '&embed=true';
+
//trim slashes from the end of the regex for this dir
$match = rtrim($match, '/');
+
//get rid of brackets
$submatchbase = str_replace( array('(', ')'), '', $match);
@@ -1040,6 +1049,7 @@ class WP_Rewrite {
$sub1feed = $sub1 . $feedregex; //and /feed/(atom|...)
$sub1feed2 = $sub1 . $feedregex2; //and /(feed|atom...)
$sub1comment = $sub1 . $commentregex; //and /comment-page-xx
+ $sub1embed = $sub1 . $embedregex; //and /embed/...
//add another rule to match attachments in the explicit form:
///attachment/some-text
@@ -1048,12 +1058,14 @@ class WP_Rewrite {
$sub2feed = $sub2 . $feedregex; //feeds, /attachment/feed/(atom|...)
$sub2feed2 = $sub2 . $feedregex2; //and feeds again on to this /attachment/(feed|atom...)
$sub2comment = $sub2 . $commentregex; //and /comment-page-xx
+ $sub2embed = $sub2 . $embedregex; //and /embed/...
//create queries for these extra tag-ons we've just dealt with
$subquery = $index . '?attachment=' . $this->preg_index(1);
$subtbquery = $subquery . '&tb=1';
$subfeedquery = $subquery . '&feed=' . $this->preg_index(2);
$subcommentquery = $subquery . '&cpage=' . $this->preg_index(2);
+ $subembedquery = $subquery . '&embed=true';
//do endpoints for attachments
if ( !empty($endpoints) ) {
@@ -1092,10 +1104,16 @@ class WP_Rewrite {
//add trackback
$rewrite = array_merge(array($trackbackmatch => $trackbackquery), $rewrite);
+ // add embed
+ $rewrite = array_merge( array( $embedmatch => $embedquery ), $rewrite );
+
//add regexes/queries for attachments, attachment trackbacks and so on
- if ( ! $page ) //require /attachment/stuff form for pages because of confusion with subpages
- $rewrite = array_merge($rewrite, array($sub1 => $subquery, $sub1tb => $subtbquery, $sub1feed => $subfeedquery, $sub1feed2 => $subfeedquery, $sub1comment => $subcommentquery));
- $rewrite = array_merge(array($sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery, $sub2comment => $subcommentquery), $rewrite);
+ if ( ! $page ) {
+ //require /attachment/stuff form for pages because of confusion with subpages
+ $rewrite = array_merge( $rewrite, array($sub1 => $subquery, $sub1tb => $subtbquery, $sub1feed => $subfeedquery, $sub1feed2 => $subfeedquery, $sub1comment => $subcommentquery, $sub1embed => $subembedquery ) );
+ }
+
+ $rewrite = array_merge( array( $sub2 => $subquery, $sub2tb => $subtbquery, $sub2feed => $subfeedquery, $sub2feed2 => $subfeedquery, $sub2comment => $subcommentquery, $sub2embed => $subembedquery ), $rewrite );
}
} //if($num_toks)
//add the rules for this dir to the accumulating $post_rewrite
diff --git a/wp-includes/class-wp.php b/wp-includes/class-wp.php
index 4fe275742d..bba47ffb71 100644
--- a/wp-includes/class-wp.php
+++ b/wp-includes/class-wp.php
@@ -15,7 +15,7 @@ class WP {
* @access public
* @var array
*/
- 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');
+ 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' );
/**
* Private query variables.
diff --git a/wp-includes/css/wp-oembed-embed.css b/wp-includes/css/wp-oembed-embed.css
new file mode 100644
index 0000000000..7c1be9b897
--- /dev/null
+++ b/wp-includes/css/wp-oembed-embed.css
@@ -0,0 +1,359 @@
+html, body {
+ padding: 0;
+ margin: 0;
+}
+
+body {
+ font-family: sans-serif;
+}
+
+/* Text meant only for screen readers */
+.screen-reader-text {
+ clip: rect(1px, 1px, 1px, 1px);
+ height: 1px;
+ overflow: hidden;
+ position: absolute !important;
+ width: 1px;
+}
+
+/* Dashicons */
+.dashicons {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ -webkit-background-size: 20px 20px;
+ background-size: 20px;
+ background-position: center;
+ -webkit-transition: background .1s ease-in;
+ transition: background .1s ease-in;
+ position: relative;
+ top: 5px;
+}
+
+.dashicons-no {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M15.55%2013.7l-2.19%202.06-3.42-3.65-3.64%203.43-2.06-2.18%203.64-3.43-3.42-3.64%202.18-2.06%203.43%203.64%203.64-3.42%202.05%202.18-3.64%203.43z%27%20fill%3D%27%23fff%27%2F%3E%3C%2Fsvg%3E");
+}
+
+.dashicons-admin-comments {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
+}
+
+.wp-embed-comments a:hover .dashicons-admin-comments {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
+}
+
+.dashicons-share {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
+}
+
+.wp-embed-share-dialog-open:hover .dashicons-share {
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
+}
+
+.wp-embed {
+ width: 100%;
+ padding: 25px;
+ font: 400 14px/1.5 'Open Sans', sans-serif;
+ color: #82878c;
+ background: white;
+ border: 1px solid #e5e5e5;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ /* Clearfix */
+ overflow: auto;
+ zoom: 1;
+}
+
+.wp-embed a {
+ color: #82878c;
+ text-decoration: none;
+}
+
+.wp-embed a:hover {
+ text-decoration: underline;
+}
+
+.wp-embed-featured-image {
+ margin-bottom: 20px;
+}
+
+.wp-embed-featured-image img {
+ width: 100%;
+ height: auto;
+ border: none;
+}
+
+.wp-embed-featured-image.square {
+ float: left;
+ max-width: 160px;
+ margin-right: 20px;
+}
+
+.wp-embed p {
+ margin: 0;
+}
+
+p.wp-embed-heading {
+ margin: 0 0 15px;
+ font-weight: bold;
+ font-size: 22px;
+ line-height: 1.3;
+}
+
+.wp-embed-heading a {
+ color: #32373c;
+}
+
+.wp-embed .wp-embed-more {
+ color: #b4b9be;
+}
+
+.wp-embed-footer {
+ display: table;
+ width: 100%;
+ margin-top: 30px;
+}
+
+.wp-embed-site-icon {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+ height: 25px;
+ width: 25px;
+ border: 0;
+}
+
+.wp-embed-site-title {
+ font-weight: bold;
+ line-height: 25px;
+}
+
+.wp-embed-site-title a {
+ position: relative;
+ display: inline-block;
+ padding-left: 35px;
+}
+
+.wp-embed-site-title,
+.wp-embed-meta {
+ display: table-cell;
+}
+
+.wp-embed-meta {
+ text-align: right;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+.wp-embed-comments,
+.wp-embed-share {
+ display: inline;
+}
+
+.wp-embed-meta a:hover {
+ text-decoration: none;
+ color: #0073aa;
+}
+
+.wp-embed-comments a {
+ line-height: 25px;
+ display: inline-block;
+}
+
+.wp-embed-comments + .wp-embed-share {
+ margin-left: 10px;
+}
+
+.wp-embed-share-dialog {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(10, 10, 10, 0.9);
+ color: #fff;
+ opacity: 1;
+ transition: opacity .25s ease-in-out;
+ -moz-transition: opacity .25s ease-in-out;
+ -webkit-transition: opacity .25s ease-in-out;
+}
+
+.wp-embed-share-dialog.hidden {
+ opacity: 0;
+ visibility: hidden;
+}
+
+.wp-embed-share-dialog-open,
+.wp-embed-share-dialog-close {
+ margin: -8px 0 0;
+ padding: 0;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ outline: none;
+}
+
+.wp-embed-share-dialog-open .dashicons,
+.wp-embed-share-dialog-close .dashicons {
+ padding: 4px;
+}
+
+.wp-embed-share-dialog-open .dashicons {
+ top: 8px;
+}
+
+.wp-embed-share-dialog-open:focus .dashicons,
+.wp-embed-share-dialog-close:focus .dashicons {
+ -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
+ box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
+ -webkit-border-radius: 100%;
+ border-radius: 100%;
+}
+
+.wp-embed-share-dialog-close {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ font-size: 22px;
+}
+
+.wp-embed-share-dialog-close:hover {
+ text-decoration: none;
+}
+
+.wp-embed-share-dialog-close .dashicons {
+ height: 24px;
+ width: 24px;
+ -webkit-background-size: 24px 24px;
+ background-size: 24px;
+}
+
+.wp-embed-share-dialog-content {
+ height: 100%;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+ overflow: hidden;
+}
+
+.wp-embed-share-dialog-text {
+ margin-top: 25px;
+ padding: 20px;
+}
+
+.wp-embed-share-tabs {
+ margin: 0 0 20px;
+ padding: 0;
+ list-style: none;
+}
+
+.wp-embed-share-tab-button {
+ display: inline;
+}
+
+.wp-embed-share-tab-button button {
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: transparent;
+ font-size: 16px;
+ line-height: 1.3;
+ color: #aaa;
+ cursor: pointer;
+ -webkit-transition: color .1s ease-in;
+ transition: color .1s ease-in;
+}
+
+.wp-embed-share-tab-button [aria-selected="true"] {
+ color: #fff;
+}
+
+.wp-embed-share-tab-button button:hover {
+ color: #fff;
+}
+
+.wp-embed-share-tab-button + .wp-embed-share-tab-button {
+ margin: 0 0 0 10px;
+ padding: 0 0 0 11px;
+ border-left: 1px solid #aaa;
+}
+
+.wp-embed-share-tab[aria-hidden="true"] {
+ display: none;
+}
+
+p.wp-embed-share-description {
+ margin: 0;
+ font-size: 14px;
+ line-height: 1;
+ font-style: italic;
+ color: #aaa;
+}
+
+.wp-embed-share-input {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ border: none;
+ height: 28px;
+ margin: 0 0 10px 0;
+ padding: 0 5px;
+ font: 400 14px/1.5 'Open Sans', sans-serif;
+ resize: none;
+ cursor: text;
+}
+
+textarea.wp-embed-share-input {
+ height: 72px;
+}
+
+html[dir="rtl"] .wp-embed-featured-image.square {
+ float: right;
+ margin-right: 0;
+
+ margin-left: 20px;
+}
+
+html[dir="rtl"] .wp-embed-site-title a {
+ padding-left: 0;
+ padding-right: 35px;
+}
+
+html[dir="rtl"] .wp-embed-site-icon {
+ margin-right: 0;
+ margin-left: 10px;
+ left: auto;
+ right: 0;
+}
+
+html[dir="rtl"] .wp-embed-meta {
+ text-align: left;
+}
+
+html[dir="rtl"] .wp-embed-footer {
+}
+
+html[dir="rtl"] .wp-embed-share {
+ margin-left: 0;
+ margin-right: 10px;
+}
+
+html[dir="rtl"] .wp-embed-share-dialog-close {
+ right: auto;
+ left: 20px;
+}
+
+html[dir="rtl"] .wp-embed-share-tab-button + .wp-embed-share-tab-button {
+ margin: 0 10px 0 0;
+ padding: 0 11px 0 0;
+ border-left: none;
+ border-right: 1px solid #aaa;
+}
diff --git a/wp-includes/css/wp-oembed-embed.min.css b/wp-includes/css/wp-oembed-embed.min.css
new file mode 100644
index 0000000000..2e36f2d500
--- /dev/null
+++ b/wp-includes/css/wp-oembed-embed.min.css
@@ -0,0 +1 @@
+body,html{padding:0;margin:0}body{font-family:sans-serif}.screen-reader-text{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute!important;width:1px}.dashicons{display:inline-block;width:20px;height:20px;background-color:transparent;background-repeat:no-repeat;-webkit-background-size:20px 20px;background-size:20px;background-position:center;-webkit-transition:background .1s ease-in;transition:background .1s ease-in;position:relative;top:5px}.dashicons-no{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M15.55%2013.7l-2.19%202.06-3.42-3.65-3.64%203.43-2.06-2.18%203.64-3.43-3.42-3.64%202.18-2.06%203.43%203.64%203.64-3.42%202.05%202.18-3.64%203.43z%27%20fill%3D%27%23fff%27%2F%3E%3C%2Fsvg%3E")}.dashicons-admin-comments{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E")}.wp-embed-comments a:hover .dashicons-admin-comments{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E")}.dashicons-share{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E")}.wp-embed-share-dialog-open:hover .dashicons-share{background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E")}.wp-embed{width:100%;padding:25px;font:400 14px/1.5 'Open Sans',sans-serif;color:#82878c;background:#fff;border:1px solid #e5e5e5;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;overflow:auto;zoom:1}.wp-embed a{color:#82878c;text-decoration:none}.wp-embed a:hover{text-decoration:underline}.wp-embed-featured-image{margin-bottom:20px}.wp-embed-featured-image img{width:100%;height:auto;border:none}.wp-embed-featured-image.square{float:left;max-width:10pc;margin-right:20px}.wp-embed p{margin:0}p.wp-embed-heading{margin:0 0 15px;font-weight:700;font-size:22px;line-height:1.3}.wp-embed-heading a{color:#32373c}.wp-embed .wp-embed-more{color:#b4b9be}.wp-embed-footer{display:table;width:100%;margin-top:30px}.wp-embed-site-icon{position:absolute;top:50%;left:0;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%);height:25px;width:25px;border:0}.wp-embed-site-title{font-weight:700;line-height:25px}.wp-embed-site-title a{position:relative;display:inline-block;padding-left:35px}.wp-embed-meta,.wp-embed-site-title{display:table-cell}.wp-embed-meta{text-align:right;white-space:nowrap;vertical-align:middle}.wp-embed-comments,.wp-embed-share{display:inline}.wp-embed-meta a:hover{text-decoration:none;color:#0073aa}.wp-embed-comments a{line-height:25px;display:inline-block}.wp-embed-comments+.wp-embed-share{margin-left:10px}.wp-embed-share-dialog{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(10,10,10,.9);color:#fff;opacity:1;transition:opacity .25s ease-in-out;-moz-transition:opacity .25s ease-in-out;-webkit-transition:opacity .25s ease-in-out}.wp-embed-share-dialog.hidden{opacity:0;visibility:hidden}.wp-embed-share-dialog-close,.wp-embed-share-dialog-open{margin:-8px 0 0;padding:0;background:0 0;border:none;cursor:pointer;outline:0}.wp-embed-share-dialog-close .dashicons,.wp-embed-share-dialog-open .dashicons{padding:4px}.wp-embed-share-dialog-open .dashicons{top:8px}.wp-embed-share-dialog-close:focus .dashicons,.wp-embed-share-dialog-open:focus .dashicons{-webkit-box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);-webkit-border-radius:100%;border-radius:100%}.wp-embed-share-dialog-close{position:absolute;top:20px;right:20px;font-size:22px}.wp-embed-share-dialog-close:hover{text-decoration:none}.wp-embed-share-dialog-close .dashicons{height:24px;width:24px;-webkit-background-size:24px 24px;background-size:24px}.wp-embed-share-dialog-content{height:100%;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;overflow:hidden}.wp-embed-share-dialog-text{margin-top:25px;padding:20px}.wp-embed-share-tabs{margin:0 0 20px;padding:0;list-style:none}.wp-embed-share-tab-button{display:inline}.wp-embed-share-tab-button button{margin:0;padding:0;border:none;background:0 0;font-size:1pc;line-height:1.3;color:#aaa;cursor:pointer;-webkit-transition:color .1s ease-in;transition:color .1s ease-in}.wp-embed-share-tab-button [aria-selected=true],.wp-embed-share-tab-button button:hover{color:#fff}.wp-embed-share-tab-button+.wp-embed-share-tab-button{margin:0 0 0 10px;padding:0 0 0 11px;border-left:1px solid #aaa}.wp-embed-share-tab[aria-hidden=true]{display:none}p.wp-embed-share-description{margin:0;font-size:14px;line-height:1;font-style:italic;color:#aaa}.wp-embed-share-input{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:none;height:28px;margin:0 0 10px;padding:0 5px;font:400 14px/1.5 'Open Sans',sans-serif;resize:none;cursor:text}textarea.wp-embed-share-input{height:72px}html[dir=rtl] .wp-embed-featured-image.square{float:right;margin-right:0;margin-left:20px}html[dir=rtl] .wp-embed-site-title a{padding-left:0;padding-right:35px}html[dir=rtl] .wp-embed-site-icon{margin-right:0;margin-left:10px;left:auto;right:0}html[dir=rtl] .wp-embed-meta{text-align:left}html[dir=rtl] .wp-embed-share{margin-left:0;margin-right:10px}html[dir=rtl] .wp-embed-share-dialog-close{right:auto;left:20px}html[dir=rtl] .wp-embed-share-tab-button+.wp-embed-share-tab-button{margin:0 10px 0 0;padding:0 11px 0 0;border-left:none;border-right:1px solid #aaa}
\ No newline at end of file
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index c9eb06b133..20dbaeab91 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -422,4 +422,33 @@ add_action( 'media_buttons', 'media_buttons' );
add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 );
add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
+// Embeds
+
+add_action( 'parse_query', 'wp_oembed_parse_query' );
+
+add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
+add_action( 'wp_head', 'wp_oembed_add_host_js' );
+
+add_action( 'oembed_head', 'print_emoji_detection_script' );
+add_action( 'oembed_head', 'print_emoji_styles' );
+add_action( 'oembed_head', 'print_oembed_embed_styles' );
+add_action( 'oembed_head', 'print_oembed_embed_scripts' );
+add_action( 'oembed_head', 'wp_print_head_scripts', 20 );
+add_action( 'oembed_head', 'wp_print_styles', 20 );
+add_action( 'oembed_head', 'wp_no_robots' );
+add_action( 'oembed_head', 'rel_canonical' );
+add_action( 'oembed_head', 'locale_stylesheet' );
+
+add_action( 'oembed_footer', 'wp_print_footer_scripts', 20 );
+
+add_filter( 'excerpt_more', 'wp_oembed_excerpt_more', 20 );
+add_filter( 'the_excerpt_embed', 'wptexturize' );
+add_filter( 'the_excerpt_embed', 'convert_chars' );
+add_filter( 'the_excerpt_embed', 'wpautop' );
+add_filter( 'the_excerpt_embed', 'shortcode_unautop' );
+add_filter( 'the_excerpt_embed', 'wp_oembed_excerpt_attachment' );
+
+add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 );
+add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
+
unset( $filter, $action );
diff --git a/wp-includes/embed-functions.php b/wp-includes/embed-functions.php
index 2fc255549b..ad5bfd711e 100644
--- a/wp-includes/embed-functions.php
+++ b/wp-includes/embed-functions.php
@@ -326,3 +326,529 @@ function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
*/
return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
}
+
+/**
+ * Parse an oEmbed API query.
+ *
+ * @since 4.4.0
+ */
+function wp_oembed_parse_query( $wp_query ) {
+ $controller = new WP_oEmbed_Controller;
+ $controller->parse_query( $wp_query );
+}
+
+/**
+ * Adds oEmbed discovery links in the website .
+ *
+ * @since 4.4.0
+ */
+function wp_oembed_add_discovery_links() {
+ $output = '';
+
+ if ( is_singular() ) {
+ $output .= '' . "\n";
+ $output .= '' . "\n";
+ }
+
+ /**
+ * Filter the oEmbed discovery links.
+ *
+ * @since 4.4.0
+ *
+ * @param string $output HTML of the discovery links.
+ */
+ echo apply_filters( 'oembed_discovery_links', $output );
+}
+
+/**
+ * Add the necessary JavaScript to communicate with the embedded iframes.
+ *
+ * @since 4.4.0
+ */
+function wp_oembed_add_host_js() {
+ wp_enqueue_script( 'wp-oembed' );
+}
+
+
+/**
+ * Get the URL to embed a specific post in an iframe.
+ *
+ * @since 4.4.0
+ *
+ * @param int|WP_Post $post Optional. Post ID or object. Defaults to the current post.
+ * @return string|false The post embed URL on success, false if the post doesn't exist.
+ */
+function get_post_embed_url( $post = null ) {
+ $post = get_post( $post );
+
+ if ( ! $post ) {
+ return false;
+ }
+
+ if ( get_option( 'permalink_structure' ) ) {
+ $embed_url = trailingslashit( get_permalink( $post ) ) . user_trailingslashit( 'embed' );
+ } else {
+ $embed_url = add_query_arg( array( 'embed' => 'true' ), get_permalink( $post ) );
+ }
+
+ /**
+ * Filter the URL to embed a specific post.
+ *
+ * @since 4.4.0
+ *
+ * @param string $embed_url The post embed URL.
+ * @param WP_Post $post The corresponding post object.
+ */
+ return esc_url_raw( apply_filters( 'post_embed_url', $embed_url, $post ) );
+}
+
+/**
+ * Get the oEmbed endpoint URL for a given permalink.
+ *
+ * Pass an empty string as the first argument
+ * to get the endpoint base URL.
+ *
+ * @since 4.4.0
+ *
+ * @param string $permalink Optional. The permalink used for the `url` query arg. Default empty.
+ * @param string $format Optional. The requested response format. Default 'json'.
+ * @return string The oEmbed endpoint URL.
+ */
+function get_oembed_endpoint_url( $permalink = '', $format = 'json' ) {
+ $url = add_query_arg( array( 'oembed' => 'true' ), home_url( '/' ) );
+
+ if ( 'json' === $format ) {
+ $format = false;
+ }
+
+ if ( '' !== $permalink ) {
+ $url = add_query_arg( array(
+ 'url' => $permalink,
+ 'format' => $format,
+ ), $url );
+ }
+
+ /**
+ * Filter the oEmbed endpoint URL.
+ *
+ * @since 4.4.0
+ *
+ * @param string $url The URL to the oEmbed endpoint.
+ * @param string $permalink The permalink used for the `url` query arg.
+ * @param string $format The requested response format.
+ */
+ return apply_filters( 'oembed_endpoint_url', $url, $permalink, $format );
+}
+
+/**
+ * Get the embed code for a specific post.
+ *
+ * @since 4.4.0
+ *
+ * @param int|WP_Post $post Optional. Post ID or object. Default is global `$post`.
+ * @param int $width The width for the response.
+ * @param int $height The height for the response.
+ * @return string|false Embed code on success, false if post doesn't exist.
+ */
+function get_post_embed_html( $post = null, $width, $height ) {
+ $post = get_post( $post );
+
+ if ( ! $post ) {
+ return false;
+ }
+
+ $embed_url = get_post_embed_url( $post );
+
+ $output = "";
+
+ $output .= sprintf(
+ '',
+ esc_url( $embed_url ),
+ absint( $width ),
+ absint( $height ),
+ esc_attr__( 'Embedded WordPress Post', 'oembed-api' )
+ );
+
+ /**
+ * Filters the oEmbed HTML output.
+ *
+ * @since 4.4.0
+ *
+ * @param string $output The default HTML.
+ * @param WP_Post $post Current post object.
+ * @param int $width Width of the response.
+ * @param int $height Height of the response.
+ */
+ return apply_filters( 'oembed_html', $output, $post, $width, $height );
+}
+
+/**
+ * Get the oEmbed response data for a given post.
+ *
+ * @since 4.4.0
+ *
+ * @param WP_Post|int $post Optional. Post object or ID. Default is global `$post`.
+ * @param int $width The requested width.
+ * @return array|false Response data on success, false if post doesn't exist.
+ */
+function get_oembed_response_data( $post = null, $width ) {
+ $post = get_post( $post );
+
+ if ( ! $post ) {
+ return false;
+ }
+
+ if ( 'publish' !== get_post_status( $post ) ) {
+ return false;
+ }
+
+ /**
+ * Filter the allowed minimum width for the oEmbed response.
+ *
+ * @param int $width The minimum width. Defaults to 200.
+ */
+ $minwidth = apply_filters( 'oembed_minwidth', 200 );
+
+ /**
+ * Filter the allowed maximum width for the oEmbed response.
+ *
+ * @param int $width The maximum width. Defaults to 600.
+ */
+ $maxwidth = apply_filters( 'oembed_maxwidth', 600 );
+
+ if ( $width < $minwidth ) {
+ $width = $minwidth;
+ } else if ( $width > $maxwidth ) {
+ $width = $maxwidth;
+ }
+
+ $height = ceil( $width / 16 * 9 );
+
+ if ( 200 > $height ) {
+ $height = 200;
+ }
+
+ $data = array(
+ 'version' => '1.0',
+ 'provider_name' => get_bloginfo( 'name' ),
+ 'provider_url' => get_home_url(),
+ 'author_name' => get_bloginfo( 'name' ),
+ 'author_url' => get_home_url(),
+ 'title' => $post->post_title,
+ 'type' => 'link',
+ );
+
+ $author = get_userdata( $post->post_author );
+
+ if ( $author ) {
+ $data['author_name'] = $author->display_name;
+ $data['author_url'] = get_author_posts_url( $author->ID );
+ }
+
+ /**
+ * Filter the oEmbed response data.
+ *
+ * @since 4.4.0
+ *
+ * @param array $data The response data.
+ * @param WP_Post $post The post object.
+ * @param int $width The requested width.
+ * @param int $height The calculated height.
+ */
+ return apply_filters( 'oembed_response_data', $data, $post, $width, $height );
+}
+
+/**
+ * Filters the oEmbed response data to return an iframe embed code.
+ *
+ * @since 4.4.0
+ *
+ * @param array $data The response data.
+ * @param WP_Post $post The post object.
+ * @param int $width The requested width.
+ * @param int $height The calculated height.
+ * @return array The modified response data.
+ */
+function get_oembed_response_data_rich( $data, $post, $width, $height ) {
+ $data['width'] = absint( $width );
+ $data['height'] = absint( $height );
+ $data['type'] = 'rich';
+ $data['html'] = get_post_embed_html( $post, $width, $height );
+
+ // Add post thumbnail to response if available.
+ $thumbnail_id = false;
+
+ if ( has_post_thumbnail( $post->ID ) ) {
+ $thumbnail_id = get_post_thumbnail_id( $post->ID );
+ }
+
+ if ( 'attachment' === get_post_type( $post ) ) {
+ if ( wp_attachment_is_image( $post ) ) {
+ $thumbnail_id = $post->ID;
+ } else if ( wp_attachment_is( 'video', $post ) ) {
+ $thumbnail_id = get_post_thumbnail_id( $post );
+ $data['type'] = 'video';
+ }
+ }
+
+ if ( $thumbnail_id ) {
+ list( $thumbnail_url, $thumbnail_width, $thumbnail_height ) = wp_get_attachment_image_src( $thumbnail_id, array( $width, 99999 ) );
+ $data['thumbnail_url'] = $thumbnail_url;
+ $data['thumbnail_width'] = $thumbnail_width;
+ $data['thumbnail_height'] = $thumbnail_height;
+ }
+
+ return $data;
+}
+
+/**
+ * Ensures that the specified format is either 'json' or 'xml'.
+ *
+ * @since 4.4.0
+ *
+ * @param string $format The oEmbed response format. Accepts 'json', 'xml'.
+ * @return string The format, either 'xml' or 'json'. Default 'json'.
+ */
+function wp_oembed_ensure_format( $format ) {
+ if ( ! in_array( $format, array( 'json', 'xml' ), true ) ) {
+ return 'json';
+ }
+
+ return $format;
+}
+
+/**
+ * Creates an XML string from a given array.
+ *
+ * @since 4.4.0
+ * @access private
+ *
+ * @param array $data The original oEmbed response data.
+ * @param SimpleXMLElement $node Optional. XML node to append the result to recursively.
+ * @return string|false XML string on success, false on error.
+ */
+function _oembed_create_xml( $data, $node = null ) {
+ if ( ! is_array( $data ) || empty( $data ) ) {
+ return false;
+ }
+
+ if ( null === $node ) {
+ $node = new SimpleXMLElement( '' );
+ }
+
+ foreach ( $data as $key => $value ) {
+ if ( is_numeric( $key ) ) {
+ $key = 'oembed';
+ }
+
+ if ( is_array( $value ) ) {
+ $item = $node->addChild( $key );
+ _oembed_create_xml( $value, $item );
+ } else {
+ $node->addChild( $key, esc_html( $value ) );
+ }
+ }
+
+ return $node->asXML();
+}
+
+/**
+ * Filters the returned oEmbed HTML.
+ *
+ * If the $url isn't on the trusted providers list,
+ * we need to filter the HTML heavily for security.
+ *
+ * Only filters 'rich' and 'html' response types.
+ *
+ * @since 4.4.0
+ *
+ * @param string $return The returned oEmbed HTML.
+ * @param object $data A data object result from an oEmbed provider.
+ * @param string $url The URL of the content to be embedded.
+ * @return string The filtered and sanitized oEmbed result.
+ */
+function wp_filter_oembed_result( $return, $data, $url ) {
+ if ( false === $return || ! in_array( $data->type, array( 'rich', 'video' ) ) ) {
+ return $return;
+ }
+
+ require_once( ABSPATH . WPINC . '/class-oembed.php' );
+ $wp_oembed = _wp_oembed_get_object();
+
+ // Don't modify the HTML for trusted providers.
+ if ( false !== $wp_oembed->get_provider( $url, array( 'discover' => false ) ) ) {
+ return $return;
+ }
+
+ $allowed_html = array(
+ 'iframe' => array(
+ 'src' => true,
+ 'width' => true,
+ 'height' => true,
+ 'frameborder' => true,
+ 'marginwidth' => true,
+ 'marginheight' => true,
+ 'scrolling' => true,
+ 'title' => true,
+ 'class' => true,
+ ),
+ );
+
+ $html = wp_kses( $return, $allowed_html );
+ preg_match( '|^.*().*$|m', $html, $iframes );
+
+ if ( empty( $iframes ) ) {
+ return false;
+ }
+
+ $html = str_replace( '