WordPress.org

Make WordPress Core

Ticket #32522: 32522.4.diff

File 32522.4.diff, 109.5 KB (added by pento, 6 years ago)
  • Gruntfile.js

     
    528528                        emoji: {
    529529                                src: BUILD_DIR + 'wp-includes/formatting.php',
    530530                                dest: '.'
     531                        },
     532                        oembed: {
     533                                src: BUILD_DIR + 'wp-includes/oembed-functions.php',
     534                                dest: '.'
    531535                        }
    532536                },
    533537                _watch: {
     
    647651                'clean:tinymce',
    648652                'concat:emoji',
    649653                'includes:emoji',
     654                'includes:oembed',
    650655                'jsvalidate:build'
    651656        ] );
    652657
  • src/wp-admin/network/site-new.php

     
    4747        // If not a subdomain install, make sure the domain isn't a reserved word
    4848        if ( ! is_subdomain_install() ) {
    4949                /** This filter is documented in wp-includes/ms-functions.php */
    50                 $subdirectory_reserved_names = apply_filters( 'subdirectory_reserved_names', array( 'page', 'comments', 'blog', 'files', 'feed', 'wp-admin', 'wp-content', 'wp-includes', 'wp-json' ) );
     50                $subdirectory_reserved_names = apply_filters( 'subdirectory_reserved_names', array( 'page', 'comments', 'blog', 'embed', 'files', 'feed', 'wp-admin', 'wp-content', 'wp-includes', 'wp-json' ) );
    5151                if ( in_array( $domain, $subdirectory_reserved_names ) )
    5252                        wp_die( sprintf( __('The following words are reserved for use by WordPress functions and cannot be used as blog names: <code>%s</code>' ), implode( '</code>, <code>', $subdirectory_reserved_names ) ) );
    5353        }
  • src/wp-includes/admin-bar.php

     
    898898        if ( defined('XMLRPC_REQUEST') || defined('DOING_AJAX') || defined('IFRAME_REQUEST') )
    899899                return false;
    900900
     901        if ( is_embed() ) {
     902                return false;
     903        }
     904
    901905        // Integrated into the admin.
    902906        if ( is_admin() )
    903907                return true;
  • src/wp-includes/class-wp-editor.php

     
    401401                                                'wplink',
    402402                                                'wpdialogs',
    403403                                                'wptextpattern',
    404                                                 'wpview'
     404                                                'wpview',
     405                                                'wpoembed',
    405406                                        );
    406407
    407408                                        if ( ! self::$has_medialib ) {
  • src/wp-includes/class-wp-embed.php

     
    233233                         * Filter whether to inspect the given URL for discoverable link tags.
    234234                         *
    235235                         * @since 2.9.0
     236                         * @since 4.4.0 The default value changed to true.
    236237                         *
    237238                         * @see WP_oEmbed::discover()
    238239                         *
    239                          * @param bool $enable Whether to enable `<link>` tag discovery. Default false.
     240                         * @param bool $enable Whether to enable `<link>` tag discovery. Default true.
    240241                         */
    241                         $attr['discover'] = ( apply_filters( 'embed_oembed_discover', false ) && author_can( $post_ID, 'unfiltered_html' ) );
     242                        $attr['discover'] = ( apply_filters( 'embed_oembed_discover', true ) );
    242243
    243244                        // Use oEmbed to get the HTML
    244245                        $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 */
     18final 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

     
    861861                $trackbackregex = 'trackback/?$';
    862862                $pageregex = $this->pagination_base . '/?([0-9]{1,})/?$';
    863863                $commentregex = $this->comments_pagination_base . '-([0-9]{1,})/?$';
     864                $embedregex = 'embed/?$';
    864865
    865866                //build up an array of endpoint regexes to append => queries to append
    866867                if ( $endpoints ) {
     
    884885                $index = $this->index; //probably 'index.php'
    885886                $feedindex = $index;
    886887                $trackbackindex = $index;
     888                $embedindex = $index;
     889
    887890                //build a list from the rewritecode and queryreplace arrays, that will look something like
    888891                //tagname=$matches[i] where i is the current $i
    889892                $queries = array();
     
    10291032                                        //create query and regex for trackback
    10301033                                        $trackbackmatch = $match . $trackbackregex;
    10311034                                        $trackbackquery = $trackbackindex . '?' . $query . '&tb=1';
     1035
     1036                                        // Create query and regex for embeds.
     1037                                        $embedmatch = $match . $embedregex;
     1038                                        $embedquery = $embedindex . '?' . $query . '&embed=true';
     1039
    10321040                                        //trim slashes from the end of the regex for this dir
    10331041                                        $match = rtrim($match, '/');
     1042
    10341043                                        //get rid of brackets
    10351044                                        $submatchbase = str_replace( array('(', ')'), '', $match);
    10361045
     
    10401049                                        $sub1feed = $sub1 . $feedregex; //and <permalink>/feed/(atom|...)
    10411050                                        $sub1feed2 = $sub1 . $feedregex2; //and <permalink>/(feed|atom...)
    10421051                                        $sub1comment = $sub1 . $commentregex; //and <permalink>/comment-page-xx
     1052                                        $sub1embed = $sub1 . $embedregex; //and <permalink>/embed/...
    10431053
    10441054                                        //add another rule to match attachments in the explicit form:
    10451055                                        //<permalink>/attachment/some-text
     
    10481058                                        $sub2feed = $sub2 . $feedregex;    //feeds, <permalink>/attachment/feed/(atom|...)
    10491059                                        $sub2feed2 = $sub2 . $feedregex2;  //and feeds again on to this <permalink>/attachment/(feed|atom...)
    10501060                                        $sub2comment = $sub2 . $commentregex; //and <permalink>/comment-page-xx
     1061                                        $sub2embed = $sub2 . $embedregex; //and <permalink>/embed/...
    10511062
    10521063                                        //create queries for these extra tag-ons we've just dealt with
    10531064                                        $subquery = $index . '?attachment=' . $this->preg_index(1);
     
    10541065                                        $subtbquery = $subquery . '&tb=1';
    10551066                                        $subfeedquery = $subquery . '&feed=' . $this->preg_index(2);
    10561067                                        $subcommentquery = $subquery . '&cpage=' . $this->preg_index(2);
     1068                                        $subembedquery = $subquery . '&embed=true';
    10571069
    10581070                                        //do endpoints for attachments
    10591071                                        if ( !empty($endpoints) ) {
     
    10921104                                        //add trackback
    10931105                                        $rewrite = array_merge(array($trackbackmatch => $trackbackquery), $rewrite);
    10941106
     1107                                        // add embed
     1108                                        $rewrite = array_merge( array( $embedmatch => $embedquery ), $rewrite );
     1109
    10951110                                        //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 );
    10991117                                }
    11001118                        } //if($num_toks)
    11011119                        //add the rules for this dir to the accumulating $post_rewrite
  • src/wp-includes/class-wp.php

     
    1515         * @access public
    1616         * @var array
    1717         */
    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' );
    1919
    2020        /**
    2121         * Private query variables.
  • src/wp-includes/default-filters.php

     
    421421add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 );
    422422add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
    423423
     424// Embeds
     425
     426add_action( 'parse_query', 'wp_oembed_parse_query' );
     427
     428add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
     429add_action( 'wp_head', 'wp_oembed_add_host_js' );
     430
     431add_action( 'oembed_head', 'print_emoji_detection_script' );
     432add_action( 'oembed_head', 'print_emoji_styles' );
     433add_action( 'oembed_head', 'wp_print_head_scripts', 20 );
     434add_action( 'oembed_head', 'wp_print_styles', 20 );
     435add_action( 'oembed_head', 'wp_no_robots' );
     436add_action( 'oembed_head', 'rel_canonical' );
     437add_action( 'oembed_head', 'locale_stylesheet' );
     438
     439add_action( 'oembed_footer', 'wp_print_footer_scripts', 20 );
     440
     441add_filter( 'excerpt_more', 'wp_oembed_excerpt_more', 20 );
     442add_filter( 'the_excerpt_embed', 'wptexturize' );
     443add_filter( 'the_excerpt_embed', 'convert_chars' );
     444add_filter( 'the_excerpt_embed', 'wpautop' );
     445add_filter( 'the_excerpt_embed', 'shortcode_unautop' );
     446add_filter( 'the_excerpt_embed', 'wp_oembed_excerpt_attachment' );
     447
     448add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 );
     449add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
     450
    424451unset( $filter, $action );
  • 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
     13if ( ! headers_sent() ) {
     14        header( 'X-WP-oembed: true' );
     15}
     16
     17wp_enqueue_style( 'open-sans' );
     18
     19?>
     20<!DOCTYPE html>
     21<html <?php language_attributes(); ?>>
     22<head>
     23        <title><?php wp_title( '-', true, 'right' ); ?></title>
     24        <meta http-equiv="X-UA-Compatible" content="IE=edge">
     25        <style type="text/css">
     26                html, body {
     27                        padding: 0;
     28                        margin: 0;
     29                }
     30
     31                body {
     32                        font-family: sans-serif;
     33                }
     34
     35                /* Text meant only for screen readers */
     36                .screen-reader-text {
     37                        clip: rect(1px, 1px, 1px, 1px);
     38                        height: 1px;
     39                        overflow: hidden;
     40                        position: absolute !important;
     41                        width: 1px;
     42                }
     43
     44                /* Dashicons */
     45                .dashicons {
     46                        display: inline-block;
     47                        width: 20px;
     48                        height: 20px;
     49                        background-color: transparent;
     50                        background-repeat: no-repeat;
     51                        background-size: 20px;
     52                        background-position: center;
     53                        -webkit-transition: background .1s ease-in;
     54                        transition: background .1s ease-in;
     55                        position: relative;
     56                        top: 5px;
     57                }
     58
     59                .dashicons-no {
     60                        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M15.55%2013.7l-2.19%202.06-3.42-3.65-3.64%203.43-2.06-2.18%203.64-3.43-3.42-3.64%202.18-2.06%203.43%203.64%203.64-3.42%202.05%202.18-3.64%203.43z%27%20fill%3D%27%23fff%27%2F%3E%3C%2Fsvg%3E");
     61                }
     62
     63                .dashicons-admin-comments {
     64                        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
     65                }
     66
     67                .wp-embed-comments a:hover .dashicons-admin-comments {
     68                        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
     69                }
     70
     71                .dashicons-share {
     72                        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
     73                }
     74
     75                .wp-embed-share-dialog-open:hover .dashicons-share {
     76                        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
     77                }
     78
     79                .wp-embed {
     80                        width: 100%;
     81                        padding: 25px;
     82                        font: 400 14px/1.5 'Open Sans', sans-serif;
     83                        color: #82878c;
     84                        background: white;
     85                        border: 1px solid #e5e5e5;
     86                        -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
     87                        box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
     88                        box-sizing: border-box;
     89                        /* Clearfix */
     90                        overflow: auto;
     91                        zoom: 1;
     92                }
     93
     94                .wp-embed a {
     95                        color: #82878c;
     96                        text-decoration: none;
     97                }
     98
     99                .wp-embed a:hover {
     100                        text-decoration: underline;
     101                }
     102
     103                .wp-embed-featured-image {
     104                        margin-bottom: 20px;
     105                }
     106
     107                .wp-embed-featured-image img {
     108                        width: 100%;
     109                        height: auto;
     110                        border: none;
     111                }
     112
     113                .wp-embed-featured-image.square {
     114                        float: left;
     115                        max-width: 160px;
     116                        margin-right: 20px;
     117                }
     118
     119                .wp-embed p {
     120                        margin: 0;
     121                }
     122
     123                p.wp-embed-heading {
     124                        margin: 0 0 15px;
     125                        font-weight: bold;
     126                        font-size: 22px;
     127                        line-height: 1.3;
     128                }
     129
     130                .wp-embed-heading a {
     131                        color: #32373c;
     132                }
     133
     134                .wp-embed .wp-embed-more {
     135                        color: #b4b9be;
     136                }
     137
     138                .wp-embed-footer {
     139                        display: table;
     140                        width: 100%;
     141                        margin-top: 30px;
     142                }
     143
     144                .wp-embed-site-icon {
     145                        position: absolute;
     146                        top: 50%;
     147                        left: 0;
     148                        -webkit-transform: translateY(-50%);
     149                        transform: translateY(-50%);
     150                        height: 25px;
     151                        width: 25px;
     152                        border: 0;
     153                }
     154
     155                .wp-embed-site-title {
     156                        font-weight: bold;
     157                        line-height: 25px;
     158                }
     159
     160                .wp-embed-site-title a {
     161                        position: relative;
     162                        display: inline-block;
     163                        padding-left: 35px;
     164                }
     165
     166                .wp-embed-site-title,
     167                .wp-embed-meta {
     168                        display: table-cell;
     169                }
     170
     171                .wp-embed-meta {
     172                        text-align: right;
     173                        white-space: nowrap;
     174                        vertical-align: middle;
     175                }
     176
     177                .wp-embed-comments,
     178                .wp-embed-share {
     179                        display: inline;
     180                }
     181
     182                .wp-embed-meta a:hover {
     183                        text-decoration: none;
     184                        color: #0073aa;
     185                }
     186
     187                .wp-embed-comments a {
     188                        line-height: 25px;
     189                        display: inline-block;
     190                }
     191
     192                .wp-embed-comments + .wp-embed-share {
     193                        margin-left: 10px;
     194                }
     195
     196                .wp-embed-share-dialog {
     197                        position: absolute;
     198                        top: 0;
     199                        left: 0;
     200                        right: 0;
     201                        bottom: 0;
     202                        background-color: rgba(10, 10, 10, 0.9);
     203                        color: #fff;
     204                        opacity: 1;
     205                        transition: opacity .25s ease-in-out;
     206                        -moz-transition: opacity .25s ease-in-out;
     207                        -webkit-transition: opacity .25s ease-in-out;
     208                }
     209
     210                .wp-embed-share-dialog.hidden {
     211                        opacity: 0;
     212                        visibility: hidden;
     213                }
     214
     215                .wp-embed-share-dialog-open,
     216                .wp-embed-share-dialog-close {
     217                        margin: -8px 0 0;
     218                        padding: 0;
     219                        background: transparent;
     220                        border: none;
     221                        cursor: pointer;
     222                        outline: none;
     223                }
     224
     225                .wp-embed-share-dialog-open .dashicons,
     226                .wp-embed-share-dialog-close .dashicons {
     227                        padding: 4px;
     228                }
     229
     230                .wp-embed-share-dialog-open .dashicons {
     231                        top: 8px;
     232                }
     233
     234                .wp-embed-share-dialog-open:focus .dashicons,
     235                .wp-embed-share-dialog-close:focus .dashicons {
     236                        -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
     237                        box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
     238                        -webkit-border-radius: 100%;
     239                        border-radius: 100%;
     240                }
     241
     242                .wp-embed-share-dialog-close {
     243                        position: absolute;
     244                        top: 20px;
     245                        right: 20px;
     246                        font-size: 22px;
     247                }
     248
     249                .wp-embed-share-dialog-close:hover {
     250                        text-decoration: none;
     251                }
     252
     253                .wp-embed-share-dialog-close .dashicons {
     254                        height: 24px;
     255                        width: 24px;
     256                        background-size: 24px;
     257                }
     258
     259                .wp-embed-share-dialog-content {
     260                        height: 100%;
     261                        -webkit-transform-style: preserve-3d;
     262                        -moz-transform-style: preserve-3d;
     263                        transform-style: preserve-3d;
     264                        overflow: hidden;
     265                }
     266
     267                .wp-embed-share-dialog-text {
     268                        margin-top: 25px;
     269                        padding: 20px;
     270                }
     271
     272                .wp-embed-share-tabs {
     273                        margin: 0 0 20px;
     274                        padding: 0;
     275                        list-style: none;
     276                }
     277
     278                .wp-embed-share-tab-button {
     279                        display: inline;
     280                }
     281
     282                .wp-embed-share-tab-button button {
     283                        margin: 0;
     284                        padding: 0;
     285                        border: none;
     286                        background: transparent;
     287                        font-size: 16px;
     288                        line-height: 1.3;
     289                        color: #aaa;
     290                        cursor: pointer;
     291                        -webkit-transition: color .1s ease-in;
     292                        transition: color .1s ease-in;
     293                }
     294
     295                .wp-embed-share-tab-button [aria-selected="true"] {
     296                        color: #fff;
     297                }
     298
     299                .wp-embed-share-tab-button button:hover {
     300                        color: #fff;
     301                }
     302
     303                .wp-embed-share-tab-button + .wp-embed-share-tab-button {
     304                        margin: 0 0 0 10px;
     305                        padding: 0 0 0 11px;
     306                        border-left: 1px solid #aaa;
     307                }
     308
     309                .wp-embed-share-tab[aria-hidden="true"] {
     310                        display: none;
     311                }
     312
     313                p.wp-embed-share-description {
     314                        margin: 0;
     315                        font-size: 14px;
     316                        line-height: 1;
     317                        font-style: italic;
     318                        color: #aaa;
     319                }
     320
     321                .wp-embed-share-input {
     322                        box-sizing: border-box;
     323                        width: 100%;
     324                        border: none;
     325                        height: 28px;
     326                        margin: 0 0 10px 0;
     327                        padding: 0 5px;
     328                        font: 400 14px/1.5 'Open Sans', sans-serif;
     329                        resize: none;
     330                        cursor: text;
     331                }
     332
     333                textarea.wp-embed-share-input {
     334                        height: 72px;
     335                }
     336
     337                html[dir="rtl"] .wp-embed-featured-image.square {
     338                        float: right;
     339                        margin-right: 0;
     340
     341                        margin-left: 20px;
     342                }
     343
     344                html[dir="rtl"] .wp-embed-site-title a {
     345                        padding-left: 0;
     346                        padding-right: 35px;
     347                }
     348
     349                html[dir="rtl"] .wp-embed-site-icon {
     350                        margin-right: 0;
     351                        margin-left: 10px;
     352                        left: auto;
     353                        right: 0;
     354                }
     355
     356                html[dir="rtl"] .wp-embed-meta {
     357                        text-align: left;
     358                }
     359
     360                html[dir="rtl"] .wp-embed-footer {
     361                }
     362
     363                html[dir="rtl"] .wp-embed-share {
     364                        margin-left: 0;
     365                        margin-right: 10px;
     366                }
     367
     368                html[dir="rtl"] .wp-embed-share-dialog-close {
     369                        right: auto;
     370                        left: 20px;
     371                }
     372
     373                html[dir="rtl"] .wp-embed-share-tab-button + .wp-embed-share-tab-button {
     374                        margin: 0 10px 0 0;
     375                        padding: 0 11px 0 0;
     376                        border-left: none;
     377                        border-right: 1px solid #aaa;
     378                }
     379        </style>
     380        <script type="text/javascript">
     381                (function ( window, document ) {
     382                        'use strict';
     383
     384                        var secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' ),
     385                                share_dialog, share_dialog_open, share_dialog_close, share_dialog_tabs, share_input, resizing;
     386
     387                        function sendEmbedMessage( message, value ) {
     388                                window.parent.postMessage( {
     389                                        message: message,
     390                                        value: value,
     391                                        secret: secret
     392                                }, '*' );
     393                        }
     394
     395                        function onLoad() {
     396                                share_dialog = document.querySelector( '.wp-embed-share-dialog' );
     397                                share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' );
     398                                share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' );
     399                                share_input = document.querySelectorAll( '.wp-embed-share-input' );
     400                                share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' );
     401
     402                                if ( share_input ) {
     403                                        for ( var i = 0; i < share_input.length; i++ ) {
     404                                                share_input[ i ].addEventListener( 'click', function ( e ) {
     405                                                        e.target.select();
     406                                                } );
     407                                        }
     408                                }
     409
     410                                function openSharingDialog() {
     411                                        share_dialog.className = share_dialog.className.replace( 'hidden', '' );
     412                                        share_input[ 0 ].select();
     413                                }
     414
     415                                function closeSharingDialog() {
     416                                        share_dialog.className += ' hidden';
     417                                        document.querySelector( '.wp-embed-share-dialog-open' ).focus();
     418                                }
     419
     420                                if ( share_dialog_open ) {
     421                                        share_dialog_open.addEventListener( 'click', function ( e ) {
     422                                                openSharingDialog();
     423                                                e.preventDefault();
     424                                        } );
     425                                }
     426
     427                                if ( share_dialog_close ) {
     428                                        share_dialog_close.addEventListener( 'click', function ( e ) {
     429                                                closeSharingDialog();
     430                                                e.preventDefault();
     431                                        } );
     432                                }
     433
     434                                if ( share_dialog_tabs ) {
     435                                        for ( var i = 0; i < share_dialog_tabs.length; i++ ) {
     436                                                share_dialog_tabs[ i ].addEventListener( 'click', function ( e ) {
     437                                                        var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
     438                                                        currentTab.setAttribute( 'aria-selected', 'false' );
     439                                                        document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
     440
     441                                                        e.target.setAttribute( 'aria-selected', 'true' );
     442                                                        document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
     443                                                } );
     444
     445                                                share_dialog_tabs[ i ].addEventListener( 'keydown', function ( e ) {
     446                                                        var previousSibling = e.target.parentElement.previousElementSibling,
     447                                                                nextSibling = e.target.parentElement.nextElementSibling,
     448                                                                newTab;
     449
     450                                                        if ( 37 === e.keyCode ) {
     451                                                                newTab = previousSibling;
     452                                                        } else if ( 39 === e.keyCode ) {
     453                                                                newTab = nextSibling;
     454                                                        } else {
     455                                                                return false;
     456                                                        }
     457
     458                                                        if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) {
     459                                                                newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling;
     460                                                        }
     461
     462                                                        if ( newTab ) {
     463                                                                e.target.setAttribute( 'tabindex', '-1' );
     464                                                                e.target.setAttribute( 'aria-selected', false );
     465                                                                document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
     466
     467                                                                newTab.firstElementChild.setAttribute( 'tabindex', '0' );
     468                                                                newTab.firstElementChild.setAttribute( 'aria-selected', 'true' );
     469                                                                newTab.firstElementChild.focus();
     470                                                                document.querySelector( '#' + newTab.firstElementChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
     471                                                        }
     472                                                } );
     473                                        }
     474                                }
     475
     476                                document.addEventListener( 'keydown', function ( e ) {
     477                                        if ( e.keyCode === 27 && -1 === share_dialog.className.indexOf( 'hidden' ) ) {
     478                                                closeSharingDialog();
     479                                        }
     480                                }, false );
     481
     482                                if ( window.self === window.top ) {
     483                                        return;
     484                                }
     485
     486                                /**
     487                                 * Send this document's height to the parent (embedding) site.
     488                                 */
     489                                sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
     490
     491                                /**
     492                                 * Detect clicks to external (_top) links.
     493                                 */
     494                                var links = document.getElementsByTagName( 'a' ), href;
     495                                for ( var i = 0; i < links.length; i++ ) {
     496                                        links[ i ].addEventListener( 'click', function ( e ) {
     497                                                if ( e.target.hasAttribute( 'href' ) ) {
     498                                                        href = e.target.getAttribute( 'href' );
     499                                                } else {
     500                                                        href = e.target.parentElement.getAttribute( 'href' );
     501                                                }
     502
     503                                                /**
     504                                                 * Send link target to the parent (embedding) site.
     505                                                 */
     506                                                sendEmbedMessage( 'link', href );
     507                                                e.preventDefault();
     508                                        } );
     509                                }
     510                        }
     511
     512                        document.addEventListener( 'DOMContentLoaded', onLoad, false );
     513
     514                        /**
     515                         * Iframe resize handler.
     516                         */
     517                        function onResize() {
     518                                if ( window.self === window.top ) {
     519                                        return;
     520                                }
     521
     522                                clearTimeout( resizing );
     523
     524                                resizing = setTimeout( function () {
     525                                        sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
     526                                }, 100 );
     527                        }
     528
     529                        window.addEventListener( 'resize', onResize, false );
     530                })( window, document );
     531        </script>
     532        <?php
     533        /**
     534         * Print scripts or data in the embed template <head> tag.
     535         *
     536         * @since 4.4.0
     537         */
     538        do_action( 'oembed_head' );
     539        ?>
     540</head>
     541<body <?php body_class(); ?>>
     542<?php
     543if ( have_posts() ) :
     544        while ( have_posts() ) : the_post();
     545                // Add post thumbnail to response if available.
     546                $thumbnail_id = false;
     547
     548                if ( has_post_thumbnail() ) {
     549                        $thumbnail_id = get_post_thumbnail_id();
     550                }
     551
     552                if ( 'attachment' === get_post_type() && wp_attachment_is_image() ) {
     553                        $thumbnail_id = get_the_ID();
     554                }
     555
     556                if ( $thumbnail_id ) {
     557                        $aspect_ratio = 1;
     558                        $measurements = array( 1, 1 );
     559                        $image_size   = 'full'; // Fallback.
     560
     561                        $meta = wp_get_attachment_metadata( $thumbnail_id );
     562                        if ( is_array( $meta ) ) {
     563                                foreach ( $meta['sizes'] as $size => $data ) {
     564                                        if ( $data['width'] / $data['height'] > $aspect_ratio ) {
     565                                                $aspect_ratio = $data['width'] / $data['height'];
     566                                                $measurements = array( $data['width'], $data['height'] );
     567                                                $image_size   = $size;
     568                                        }
     569                                }
     570                        }
     571
     572                        /**
     573                         * Filter the thumbnail image size for use in the embed template.
     574                         *
     575                         * @param string $image_size Thumbnail image size.
     576                         */
     577                        $image_size = apply_filters( 'oembed_thumbnail_image_size', $image_size );
     578
     579                        $shape = $measurements[0] / $measurements[1] >= 1.75 ? 'rectangular' : 'square';
     580
     581                        /**
     582                         * Filter the thumbnail shape for use in the embed template.
     583                         *
     584                         * Rectangular images are shown above the title
     585                         * while square images are shown next to the content.
     586                         *
     587                         * @since 4.4.0
     588                         *
     589                         * @param string $shape Thumbnail image shape. Either 'rectangular' or 'square'.
     590                         */
     591                        $shape = apply_filters( 'oembed_thumbnail_image_shape', $shape );
     592                }
     593                ?>
     594                <div <?php post_class( 'wp-embed' ); ?>>
     595                        <?php if ( $thumbnail_id && 'rectangular' === $shape ) : ?>
     596                                <div class="wp-embed-featured-image rectangular">
     597                                        <a href="<?php the_permalink(); ?>" target="_top">
     598                                                <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?>
     599                                        </a>
     600                                </div>
     601                        <?php endif; ?>
     602
     603                        <p class="wp-embed-heading">
     604                                <a href="<?php the_permalink(); ?>" target="_top">
     605                                        <?php the_title(); ?>
     606                                </a>
     607                        </p>
     608
     609                        <?php if ( $thumbnail_id && 'square' === $shape ) : ?>
     610                                <div class="wp-embed-featured-image square">
     611                                        <a href="<?php the_permalink(); ?>" target="_top">
     612                                                <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?>
     613                                        </a>
     614                                </div>
     615                        <?php endif; ?>
     616
     617                        <div class="wp-embed-excerpt"><?php the_excerpt_embed(); ?></div>
     618
     619                        <?php
     620                        /**
     621                         * Print additional content after the embed excerpt.
     622                         *
     623                         * @since 4.4.0
     624                         */
     625                        do_action( 'oembed_content' );
     626                        ?>
     627
     628                        <div class="wp-embed-footer">
     629                                <div class="wp-embed-site-title">
     630                                        <?php
     631                                        $site_icon_url = admin_url( 'images/w-logo-blue.png' );
     632
     633                                        if ( function_exists( 'get_site_icon_url' ) ) {
     634                                                $site_icon_url = get_site_icon_url( 32, $site_icon_url );
     635                                        }
     636
     637                                        /**
     638                                         * Filters the site icon URL for use in the embed template.
     639                                         *
     640                                         * @param string $site_icon_url The site icon URL.
     641                                         */
     642                                        $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url );
     643
     644                                        printf(
     645                                                '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>',
     646                                                esc_url( home_url() ),
     647                                                esc_url( $site_icon_url ),
     648                                                esc_attr( get_bloginfo( 'name' ) )
     649                                        );
     650                                        ?>
     651                                </div>
     652
     653                                <div class="wp-embed-meta">
     654                                        <?php
     655                                        /**
     656                                         * Print additional meta content in the embed template.
     657                                         *
     658                                         * @since 4.4.0
     659                                         */
     660                                        do_action( 'oembed_content_meta');
     661                                        ?>
     662                                        <?php if ( get_comments_number() || comments_open() ) : ?>
     663                                                <div class="wp-embed-comments">
     664                                                        <a href="<?php comments_link(); ?>" target="_top">
     665                                                                <span class="dashicons dashicons-admin-comments"></span>
     666                                                                <?php
     667                                                                printf(
     668                                                                        _n(
     669                                                                                '%s <span class="screen-reader-text">Comment</span>',
     670                                                                                '%s <span class="screen-reader-text">Comments</span>',
     671                                                                                get_comments_number(),
     672                                                                                'oembed-api'
     673                                                                        ),
     674                                                                        absint( get_comments_number() )
     675                                                                );
     676                                                                ?>
     677                                                        </a>
     678                                                </div>
     679                                        <?php endif; ?>
     680                                        <div class="wp-embed-share">
     681                                                <button type="button" class="wp-embed-share-dialog-open"
     682                                                        aria-label="<?php esc_attr_e( 'Open sharing dialog', 'oembed-api' ); ?>">
     683                                                        <span class="dashicons dashicons-share"></span>
     684                                                </button>
     685                                        </div>
     686                                </div>
     687                        </div>
     688                        <div class="wp-embed-share-dialog hidden">
     689                                <div class="wp-embed-share-dialog-content">
     690                                        <div class="wp-embed-share-dialog-text">
     691                                                <ul class="wp-embed-share-tabs" role="tablist">
     692                                                        <li id="wp-embed-share-tab-button-wordpress" class="wp-embed-share-tab-button" role="presentation">
     693                                                                <button role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed', 'oembed-api' ); ?></button>
     694                                                        </li>
     695                                                        <li id="wp-embed-share-tab-button-embed" class="wp-embed-share-tab-button" role="presentation">
     696                                                                <button role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed', 'oembed-api' ); ?></button>
     697                                                        </li>
     698                                                </ul>
     699                                                <div id="wp-embed-share-tab-wordpress" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-wordpress" aria-hidden="false">
     700                                                        <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" tabindex="0" readonly/>
     701
     702                                                        <p class="wp-embed-share-description">
     703                                                                <?php _e( 'Copy and paste this URL into your WordPress site to embed', 'oembed-api' ); ?>
     704                                                        </p>
     705                                                </div>
     706                                                <div id="wp-embed-share-tab-html" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-html" aria-hidden="true">
     707                                                        <textarea class="wp-embed-share-input" tabindex="0" readonly><?php echo esc_attr( get_post_embed_html( null, 600, 400 ) ); ?></textarea>
     708
     709                                                        <p class="wp-embed-share-description">
     710                                                                <?php _e( 'Copy and paste this code into your site to embed', 'oembed-api' ); ?>
     711                                                        </p>
     712                                                </div>
     713                                        </div>
     714
     715                                        <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog', 'oembed-api' ); ?>">
     716                                                <span class="dashicons dashicons-no"></span>
     717                                        </button>
     718                                </div>
     719                        </div>
     720                </div>
     721                <?php
     722        endwhile;
     723else :
     724        ?>
     725        <div class="wp-embed">
     726                <p class="wp-embed-heading"><?php _e( 'Page not found', 'oembed-api' ); ?></p>
     727
     728                <div class="wp-embed-excerpt">
     729                        <p><?php _e( 'Error 404! The requested content was not found.', 'oembed-api' ) ?></p>
     730                </div>
     731
     732                <div class="wp-embed-footer">
     733                        <div class="wp-embed-site-title">
     734                                <?php
     735                                $site_icon_url = admin_url( 'images/w-logo-blue.png' );
     736
     737                                if ( function_exists( 'get_site_icon_url' ) ) {
     738                                        $site_icon_url = get_site_icon_url( 32, $site_icon_url );
     739                                }
     740
     741                                /**
     742                                 * Filters the site icon URL for use in the embed template.
     743                                 *
     744                                 * @param string $site_icon_url The site icon URL.
     745                                 */
     746                                $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url );
     747
     748                                printf(
     749                                        '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>',
     750                                        esc_url( home_url() ),
     751                                        esc_url( $site_icon_url ),
     752                                        esc_attr( get_bloginfo( 'name' ) )
     753                                );
     754                                ?>
     755                        </div>
     756                </div>
     757        </div>
     758        <?php
     759endif;
     760
     761/**
     762 * Print scripts or data before the closing body tag in the embed template.
     763 *
     764 * @since 4.4.0
     765 */
     766do_action( 'oembed_footer' );
     767?>
     768</body>
     769</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.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 = 10 === new Function( "/*@cc_on return @_jscript_version; @*/" )(),
     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/media.php

     
    21772177}
    21782178
    21792179/**
    2180  * Registers an embed handler.
    2181  *
    2182  * Should probably only be used for sites that do not support oEmbed.
    2183  *
    2184  * @since 2.9.0
    2185  *
    2186  * @global WP_Embed $wp_embed
    2187  *
    2188  * @param string   $id       An internal ID/name for the handler. Needs to be unique.
    2189  * @param string   $regex    The regex that will be used to see if this handler should be used for a URL.
    2190  * @param callable $callback The callback function that will be called if the regex is matched.
    2191  * @param int      $priority Optional. Used to specify the order in which the registered handlers will
    2192  *                           be tested. Default 10.
    2193  */
    2194 function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {
    2195         global $wp_embed;
    2196         $wp_embed->register_handler( $id, $regex, $callback, $priority );
    2197 }
    2198 
    2199 /**
    2200  * Unregisters a previously-registered embed handler.
    2201  *
    2202  * @since 2.9.0
    2203  *
    2204  * @global WP_Embed $wp_embed
    2205  *
    2206  * @param string $id       The handler ID that should be removed.
    2207  * @param int    $priority Optional. The priority of the handler to be removed. Default 10.
    2208  */
    2209 function wp_embed_unregister_handler( $id, $priority = 10 ) {
    2210         global $wp_embed;
    2211         $wp_embed->unregister_handler( $id, $priority );
    2212 }
    2213 
    2214 /**
    2215  * Create default array of embed parameters.
    2216  *
    2217  * The width defaults to the content width as specified by the theme. If the
    2218  * theme does not specify a content width, then 500px is used.
    2219  *
    2220  * The default height is 1.5 times the width, or 1000px, whichever is smaller.
    2221  *
    2222  * The 'embed_defaults' filter can be used to adjust either of these values.
    2223  *
    2224  * @since 2.9.0
    2225  *
    2226  * @global int $content_width
    2227  *
    2228  * @param string $url Optional. The URL that should be embedded. Default empty.
    2229  *
    2230  * @return array Default embed parameters.
    2231  */
    2232 function wp_embed_defaults( $url = '' ) {
    2233         if ( ! empty( $GLOBALS['content_width'] ) )
    2234                 $width = (int) $GLOBALS['content_width'];
    2235 
    2236         if ( empty( $width ) )
    2237                 $width = 500;
    2238 
    2239         $height = min( ceil( $width * 1.5 ), 1000 );
    2240 
    2241         /**
    2242          * Filter the default array of embed dimensions.
    2243          *
    2244          * @since 2.9.0
    2245          *
    2246          * @param int    $width  Width of the embed in pixels.
    2247          * @param int    $height Height of the embed in pixels.
    2248          * @param string $url    The URL that should be embedded.
    2249          */
    2250         return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url );
    2251 }
    2252 
    2253 /**
    22542180 * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height.
    22552181 *
    22562182 * @since 2.9.0
     
    22732199}
    22742200
    22752201/**
    2276  * Attempts to fetch the embed HTML for a provided URL using oEmbed.
    2277  *
    2278  * @since 2.9.0
    2279  *
    2280  * @see WP_oEmbed
    2281  *
    2282  * @param string $url  The URL that should be embedded.
    2283  * @param array  $args Optional. Additional arguments and parameters for retrieving embed HTML.
    2284  *                     Default empty.
    2285  * @return false|string False on failure or the embed HTML on success.
    2286  */
    2287 function wp_oembed_get( $url, $args = '' ) {
    2288         require_once( ABSPATH . WPINC . '/class-oembed.php' );
    2289         $oembed = _wp_oembed_get_object();
    2290         return $oembed->get_html( $url, $args );
    2291 }
    2292 
    2293 /**
    2294  * Adds a URL format and oEmbed provider URL pair.
    2295  *
    2296  * @since 2.9.0
    2297  *
    2298  * @see WP_oEmbed
    2299  *
    2300  * @param string  $format   The format of URL that this provider can handle. You can use asterisks
    2301  *                          as wildcards.
    2302  * @param string  $provider The URL to the oEmbed provider.
    2303  * @param boolean $regex    Optional. Whether the `$format` parameter is in a RegEx format. Default false.
    2304  */
    2305 function wp_oembed_add_provider( $format, $provider, $regex = false ) {
    2306         require_once( ABSPATH . WPINC . '/class-oembed.php' );
    2307 
    2308         if ( did_action( 'plugins_loaded' ) ) {
    2309                 $oembed = _wp_oembed_get_object();
    2310                 $oembed->providers[$format] = array( $provider, $regex );
    2311         } else {
    2312                 WP_oEmbed::_add_provider_early( $format, $provider, $regex );
    2313         }
    2314 }
    2315 
    2316 /**
    2317  * Removes an oEmbed provider.
    2318  *
    2319  * @since 3.5.0
    2320  *
    2321  * @see WP_oEmbed
    2322  *
    2323  * @param string $format The URL format for the oEmbed provider to remove.
    2324  * @return bool Was the provider removed successfully?
    2325  */
    2326 function wp_oembed_remove_provider( $format ) {
    2327         require_once( ABSPATH . WPINC . '/class-oembed.php' );
    2328 
    2329         if ( did_action( 'plugins_loaded' ) ) {
    2330                 $oembed = _wp_oembed_get_object();
    2331 
    2332                 if ( isset( $oembed->providers[ $format ] ) ) {
    2333                         unset( $oembed->providers[ $format ] );
    2334                         return true;
    2335                 }
    2336         } else {
    2337                 WP_oEmbed::_remove_provider_early( $format );
    2338         }
    2339 
    2340         return false;
    2341 }
    2342 
    2343 /**
    2344  * Determines if default embed handlers should be loaded.
    2345  *
    2346  * Checks to make sure that the embeds library hasn't already been loaded. If
    2347  * it hasn't, then it will load the embeds library.
    2348  *
    2349  * @since 2.9.0
    2350  *
    2351  * @see wp_embed_register_handler()
    2352  */
    2353 function wp_maybe_load_embeds() {
    2354         /**
    2355          * Filter whether to load the default embed handlers.
    2356          *
    2357          * Returning a falsey value will prevent loading the default embed handlers.
    2358          *
    2359          * @since 2.9.0
    2360          *
    2361          * @param bool $maybe_load_embeds Whether to load the embeds library. Default true.
    2362          */
    2363         if ( ! apply_filters( 'load_default_embeds', true ) ) {
    2364                 return;
    2365         }
    2366 
    2367         wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/(?:v|embed)/([^/]+)#i', 'wp_embed_handler_youtube' );
    2368 
    2369         wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );
    2370 
    2371         /**
    2372          * Filter the audio embed handler callback.
    2373          *
    2374          * @since 3.6.0
    2375          *
    2376          * @param callable $handler Audio embed handler callback function.
    2377          */
    2378         wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 );
    2379 
    2380         /**
    2381          * Filter the video embed handler callback.
    2382          *
    2383          * @since 3.6.0
    2384          *
    2385          * @param callable $handler Video embed handler callback function.
    2386          */
    2387         wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 );
    2388 }
    2389 
    2390 /**
    2391  * The Google Video embed handler callback.
    2392  *
    2393  * Google Video does not support oEmbed.
    2394  *
    2395  * @see WP_Embed::register_handler()
    2396  * @see WP_Embed::shortcode()
    2397  *
    2398  * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
    2399  * @param array  $attr    Embed attributes.
    2400  * @param string $url     The original URL that was matched by the regex.
    2401  * @param array  $rawattr The original unmodified attributes.
    2402  * @return string The embed HTML.
    2403  */
    2404 function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {
    2405         // If the user supplied a fixed width AND height, use it
    2406         if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {
    2407                 $width  = (int) $rawattr['width'];
    2408                 $height = (int) $rawattr['height'];
    2409         } else {
    2410                 list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );
    2411         }
    2412 
    2413         /**
    2414          * Filter the Google Video embed output.
    2415          *
    2416          * @since 2.9.0
    2417          *
    2418          * @param string $html    Google Video HTML embed markup.
    2419          * @param array  $matches The RegEx matches from the provided regex.
    2420          * @param array  $attr    An array of embed attributes.
    2421          * @param string $url     The original URL that was matched by the regex.
    2422          * @param array  $rawattr The original unmodified attributes.
    2423          */
    2424         return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&amp;hl=en&amp;fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr );
    2425 }
    2426 
    2427 /**
    2428  * YouTube iframe embed handler callback.
    2429  *
    2430  * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is.
    2431  *
    2432  * @since 4.0.0
    2433  *
    2434  * @global WP_Embed $wp_embed
    2435  *
    2436  * @param array  $matches The RegEx matches from the provided regex when calling
    2437  *                        wp_embed_register_handler().
    2438  * @param array  $attr    Embed attributes.
    2439  * @param string $url     The original URL that was matched by the regex.
    2440  * @param array  $rawattr The original unmodified attributes.
    2441  * @return string The embed HTML.
    2442  */
    2443 function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) {
    2444         global $wp_embed;
    2445         $embed = $wp_embed->autoembed( "https://youtube.com/watch?v={$matches[2]}" );
    2446 
    2447         /**
    2448          * Filter the YoutTube embed output.
    2449          *
    2450          * @since 4.0.0
    2451          *
    2452          * @see wp_embed_handler_youtube()
    2453          *
    2454          * @param string $embed   YouTube embed output.
    2455          * @param array  $attr    An array of embed attributes.
    2456          * @param string $url     The original URL that was matched by the regex.
    2457          * @param array  $rawattr The original unmodified attributes.
    2458          */
    2459         return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr );
    2460 }
    2461 
    2462 /**
    2463  * Audio embed handler callback.
    2464  *
    2465  * @since 3.6.0
    2466  *
    2467  * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
    2468  * @param array  $attr Embed attributes.
    2469  * @param string $url The original URL that was matched by the regex.
    2470  * @param array  $rawattr The original unmodified attributes.
    2471  * @return string The embed HTML.
    2472  */
    2473 function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) {
    2474         $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) );
    2475 
    2476         /**
    2477          * Filter the audio embed output.
    2478          *
    2479          * @since 3.6.0
    2480          *
    2481          * @param string $audio   Audio embed output.
    2482          * @param array  $attr    An array of embed attributes.
    2483          * @param string $url     The original URL that was matched by the regex.
    2484          * @param array  $rawattr The original unmodified attributes.
    2485          */
    2486         return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr );
    2487 }
    2488 
    2489 /**
    2490  * Video embed handler callback.
    2491  *
    2492  * @since 3.6.0
    2493  *
    2494  * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
    2495  * @param array  $attr    Embed attributes.
    2496  * @param string $url     The original URL that was matched by the regex.
    2497  * @param array  $rawattr The original unmodified attributes.
    2498  * @return string The embed HTML.
    2499  */
    2500 function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
    2501         $dimensions = '';
    2502         if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {
    2503                 $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );
    2504                 $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );
    2505         }
    2506         $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) );
    2507 
    2508         /**
    2509          * Filter the video embed output.
    2510          *
    2511          * @since 3.6.0
    2512          *
    2513          * @param string $video   Video embed output.
    2514          * @param array  $attr    An array of embed attributes.
    2515          * @param string $url     The original URL that was matched by the regex.
    2516          * @param array  $rawattr The original unmodified attributes.
    2517          */
    2518         return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
    2519 }
    2520 
    2521 /**
    25222202 * Converts a shorthand byte value to an integer byte value.
    25232203 *
    25242204 * @since 2.3.0
  • src/wp-includes/ms-functions.php

     
    566566                         *
    567567                         * @param array $subdirectory_reserved_names Array of reserved names.
    568568                         */
    569                         apply_filters( 'subdirectory_reserved_names', array( 'page', 'comments', 'blog', 'files', 'feed', 'wp-admin', 'wp-content', 'wp-includes', 'wp-json' ) )
     569                        apply_filters( 'subdirectory_reserved_names', array( 'page', 'comments', 'blog', 'embed', 'files', 'feed', 'wp-admin', 'wp-content', 'wp-includes', 'wp-json' ) )
    570570                );
    571571        }
    572572
  • src/wp-includes/oembed-functions.php

     
     1<?php
     2/**
     3 * WordPress API for embedding content.
     4 *
     5 * @package WordPress
     6 * @subpackage oEmbed
     7 * @since 4.4.0
     8 */
     9
     10/**
     11 * Registers an embed handler.
     12 *
     13 * Should probably only be used for sites that do not support oEmbed.
     14 *
     15 * @since 2.9.0
     16 *
     17 * @global WP_Embed $wp_embed
     18 *
     19 * @param string   $id       An internal ID/name for the handler. Needs to be unique.
     20 * @param string   $regex    The regex that will be used to see if this handler should be used for a URL.
     21 * @param callable $callback The callback function that will be called if the regex is matched.
     22 * @param int      $priority Optional. Used to specify the order in which the registered handlers will
     23 *                           be tested. Default 10.
     24 */
     25function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {
     26        global $wp_embed;
     27        $wp_embed->register_handler( $id, $regex, $callback, $priority );
     28}
     29
     30/**
     31 * Unregisters a previously-registered embed handler.
     32 *
     33 * @since 2.9.0
     34 *
     35 * @global WP_Embed $wp_embed
     36 *
     37 * @param string $id       The handler ID that should be removed.
     38 * @param int    $priority Optional. The priority of the handler to be removed. Default 10.
     39 */
     40function wp_embed_unregister_handler( $id, $priority = 10 ) {
     41        global $wp_embed;
     42        $wp_embed->unregister_handler( $id, $priority );
     43}
     44
     45/**
     46 * Create default array of embed parameters.
     47 *
     48 * The width defaults to the content width as specified by the theme. If the
     49 * theme does not specify a content width, then 500px is used.
     50 *
     51 * The default height is 1.5 times the width, or 1000px, whichever is smaller.
     52 *
     53 * The 'embed_defaults' filter can be used to adjust either of these values.
     54 *
     55 * @since 2.9.0
     56 *
     57 * @global int $content_width
     58 *
     59 * @param string $url Optional. The URL that should be embedded. Default empty.
     60 *
     61 * @return array Default embed parameters.
     62 */
     63function wp_embed_defaults( $url = '' ) {
     64        if ( ! empty( $GLOBALS['content_width'] ) )
     65                $width = (int) $GLOBALS['content_width'];
     66
     67        if ( empty( $width ) )
     68                $width = 500;
     69
     70        $height = min( ceil( $width * 1.5 ), 1000 );
     71
     72        /**
     73         * Filter the default array of embed dimensions.
     74         *
     75         * @since 2.9.0
     76         *
     77         * @param int    $width  Width of the embed in pixels.
     78         * @param int    $height Height of the embed in pixels.
     79         * @param string $url    The URL that should be embedded.
     80         */
     81        return apply_filters( 'embed_defaults', compact( 'width', 'height' ), $url );
     82}
     83
     84/**
     85 * Attempts to fetch the embed HTML for a provided URL using oEmbed.
     86 *
     87 * @since 2.9.0
     88 *
     89 * @see WP_oEmbed
     90 *
     91 * @param string $url  The URL that should be embedded.
     92 * @param array  $args Optional. Additional arguments and parameters for retrieving embed HTML.
     93 *                     Default empty.
     94 * @return false|string False on failure or the embed HTML on success.
     95 */
     96function wp_oembed_get( $url, $args = '' ) {
     97        require_once( ABSPATH . WPINC . '/class-oembed.php' );
     98        $oembed = _wp_oembed_get_object();
     99        return $oembed->get_html( $url, $args );
     100}
     101
     102/**
     103 * Adds a URL format and oEmbed provider URL pair.
     104 *
     105 * @since 2.9.0
     106 *
     107 * @see WP_oEmbed
     108 *
     109 * @param string  $format   The format of URL that this provider can handle. You can use asterisks
     110 *                          as wildcards.
     111 * @param string  $provider The URL to the oEmbed provider.
     112 * @param boolean $regex    Optional. Whether the `$format` parameter is in a RegEx format. Default false.
     113 */
     114function wp_oembed_add_provider( $format, $provider, $regex = false ) {
     115        require_once( ABSPATH . WPINC . '/class-oembed.php' );
     116
     117        if ( did_action( 'plugins_loaded' ) ) {
     118                $oembed = _wp_oembed_get_object();
     119                $oembed->providers[$format] = array( $provider, $regex );
     120        } else {
     121                WP_oEmbed::_add_provider_early( $format, $provider, $regex );
     122        }
     123}
     124
     125/**
     126 * Removes an oEmbed provider.
     127 *
     128 * @since 3.5.0
     129 *
     130 * @see WP_oEmbed
     131 *
     132 * @param string $format The URL format for the oEmbed provider to remove.
     133 * @return bool Was the provider removed successfully?
     134 */
     135function wp_oembed_remove_provider( $format ) {
     136        require_once( ABSPATH . WPINC . '/class-oembed.php' );
     137
     138        if ( did_action( 'plugins_loaded' ) ) {
     139                $oembed = _wp_oembed_get_object();
     140
     141                if ( isset( $oembed->providers[ $format ] ) ) {
     142                        unset( $oembed->providers[ $format ] );
     143                        return true;
     144                }
     145        } else {
     146                WP_oEmbed::_remove_provider_early( $format );
     147        }
     148
     149        return false;
     150}
     151
     152/**
     153 * Determines if default embed handlers should be loaded.
     154 *
     155 * Checks to make sure that the embeds library hasn't already been loaded. If
     156 * it hasn't, then it will load the embeds library.
     157 *
     158 * @since 2.9.0
     159 *
     160 * @see wp_embed_register_handler()
     161 */
     162function wp_maybe_load_embeds() {
     163        /**
     164         * Filter whether to load the default embed handlers.
     165         *
     166         * Returning a falsey value will prevent loading the default embed handlers.
     167         *
     168         * @since 2.9.0
     169         *
     170         * @param bool $maybe_load_embeds Whether to load the embeds library. Default true.
     171         */
     172        if ( ! apply_filters( 'load_default_embeds', true ) ) {
     173                return;
     174        }
     175
     176        wp_embed_register_handler( 'youtube_embed_url', '#https?://(www.)?youtube\.com/(?:v|embed)/([^/]+)#i', 'wp_embed_handler_youtube' );
     177
     178        wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );
     179
     180        /**
     181         * Filter the audio embed handler callback.
     182         *
     183         * @since 3.6.0
     184         *
     185         * @param callable $handler Audio embed handler callback function.
     186         */
     187        wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 );
     188
     189        /**
     190         * Filter the video embed handler callback.
     191         *
     192         * @since 3.6.0
     193         *
     194         * @param callable $handler Video embed handler callback function.
     195         */
     196        wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 );
     197}
     198
     199/**
     200 * The Google Video embed handler callback.
     201 *
     202 * Google Video does not support oEmbed.
     203 *
     204 * @see WP_Embed::register_handler()
     205 * @see WP_Embed::shortcode()
     206 *
     207 * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
     208 * @param array  $attr    Embed attributes.
     209 * @param string $url     The original URL that was matched by the regex.
     210 * @param array  $rawattr The original unmodified attributes.
     211 * @return string The embed HTML.
     212 */
     213function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {
     214        // If the user supplied a fixed width AND height, use it
     215        if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {
     216                $width  = (int) $rawattr['width'];
     217                $height = (int) $rawattr['height'];
     218        } else {
     219                list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );
     220        }
     221
     222        /**
     223         * Filter the Google Video embed output.
     224         *
     225         * @since 2.9.0
     226         *
     227         * @param string $html    Google Video HTML embed markup.
     228         * @param array  $matches The RegEx matches from the provided regex.
     229         * @param array  $attr    An array of embed attributes.
     230         * @param string $url     The original URL that was matched by the regex.
     231         * @param array  $rawattr The original unmodified attributes.
     232         */
     233        return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&amp;hl=en&amp;fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr );
     234}
     235
     236/**
     237 * YouTube iframe embed handler callback.
     238 *
     239 * Catches YouTube iframe embed URLs that are not parsable by oEmbed but can be translated into a URL that is.
     240 *
     241 * @since 4.0.0
     242 *
     243 * @global WP_Embed $wp_embed
     244 *
     245 * @param array  $matches The RegEx matches from the provided regex when calling
     246 *                        wp_embed_register_handler().
     247 * @param array  $attr    Embed attributes.
     248 * @param string $url     The original URL that was matched by the regex.
     249 * @param array  $rawattr The original unmodified attributes.
     250 * @return string The embed HTML.
     251 */
     252function wp_embed_handler_youtube( $matches, $attr, $url, $rawattr ) {
     253        global $wp_embed;
     254        $embed = $wp_embed->autoembed( "https://youtube.com/watch?v={$matches[2]}" );
     255
     256        /**
     257         * Filter the YoutTube embed output.
     258         *
     259         * @since 4.0.0
     260         *
     261         * @see wp_embed_handler_youtube()
     262         *
     263         * @param string $embed   YouTube embed output.
     264         * @param array  $attr    An array of embed attributes.
     265         * @param string $url     The original URL that was matched by the regex.
     266         * @param array  $rawattr The original unmodified attributes.
     267         */
     268        return apply_filters( 'wp_embed_handler_youtube', $embed, $attr, $url, $rawattr );
     269}
     270
     271/**
     272 * Audio embed handler callback.
     273 *
     274 * @since 3.6.0
     275 *
     276 * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
     277 * @param array  $attr Embed attributes.
     278 * @param string $url The original URL that was matched by the regex.
     279 * @param array  $rawattr The original unmodified attributes.
     280 * @return string The embed HTML.
     281 */
     282function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) {
     283        $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) );
     284
     285        /**
     286         * Filter the audio embed output.
     287         *
     288         * @since 3.6.0
     289         *
     290         * @param string $audio   Audio embed output.
     291         * @param array  $attr    An array of embed attributes.
     292         * @param string $url     The original URL that was matched by the regex.
     293         * @param array  $rawattr The original unmodified attributes.
     294         */
     295        return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr );
     296}
     297
     298/**
     299 * Video embed handler callback.
     300 *
     301 * @since 3.6.0
     302 *
     303 * @param array  $matches The RegEx matches from the provided regex when calling wp_embed_register_handler().
     304 * @param array  $attr    Embed attributes.
     305 * @param string $url     The original URL that was matched by the regex.
     306 * @param array  $rawattr The original unmodified attributes.
     307 * @return string The embed HTML.
     308 */
     309function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
     310        $dimensions = '';
     311        if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {
     312                $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );
     313                $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );
     314        }
     315        $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) );
     316
     317        /**
     318         * Filter the video embed output.
     319         *
     320         * @since 3.6.0
     321         *
     322         * @param string $video   Video embed output.
     323         * @param array  $attr    An array of embed attributes.
     324         * @param string $url     The original URL that was matched by the regex.
     325         * @param array  $rawattr The original unmodified attributes.
     326         */
     327        return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
     328}
     329
     330/**
     331 * Parse an oEmbed API query.
     332 *
     333 * @since 4.4.0
     334 */
     335function 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 */
     345function 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 */
     368function 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 */
     381function 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 */
     417function 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 */
     453function 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"
     478JS;
     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 */
     512function 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 */
     590function 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 */
     630function 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 */
     648function _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 */
     688function 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 */
     745function wp_oembed_excerpt_more( $more_string ) {
     746        if ( ! is_embed() ) {
     747                return $more_string;
     748        }
     749
     750        return sprintf(
     751                _x( '&hellip; %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 */
     765function 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 */
     786function wp_oembed_excerpt_attachment( $content ) {
     787        if ( is_attachment() ) {
     788                return prepend_attachment( '' );
     789        }
     790
     791        return $content;
     792}
  • src/wp-includes/query.php

     
    719719}
    720720
    721721/**
     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 */
     730function 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/**
    722742 * Is the query the main query?
    723743 *
    724744 * @since 3.3.0
     
    12011221        public $is_404 = false;
    12021222
    12031223        /**
     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        /**
    12041233         * Set if query is within comments popup window.
    12051234         *
    12061235         * @since 1.5.0
     
    18451874                if ( '404' == $qv['error'] )
    18461875                        $this->set_404();
    18471876
     1877                $this->is_embed = isset( $qv['embed'] ) && ( $this->is_singular || $this->is_404 );
     1878
    18481879                $this->query_vars_hash = md5( serialize( $this->query_vars ) );
    18491880                $this->query_vars_changed = false;
    18501881
     
    46354666        }
    46364667
    46374668        /**
     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        /**
    46384680         * Is the query the main query?
    46394681         *
    46404682         * @since 3.3.0
     
    49354977                        $link = user_trailingslashit( trailingslashit( $link ) . 'feed' );
    49364978                } elseif ( isset( $GLOBALS['wp_query']->query_vars['paged'] ) && $GLOBALS['wp_query']->query_vars['paged'] > 1 ) {
    49374979                        $link = user_trailingslashit( trailingslashit( $link ) . 'page/' . $GLOBALS['wp_query']->query_vars['paged'] );
     4980                } elseif( is_embed() ) {
     4981                        $link = user_trailingslashit( trailingslashit( $link ) . 'embed' );
    49384982                } elseif ( is_404() ) {
    49394983                        // Add rewrite endpoints if necessary.
    49404984                        foreach ( $wp_rewrite->endpoints as $endpoint ) {
  • src/wp-includes/script-loader.php

     
    466466                ),
    467467        ) );
    468468
     469        $scripts->add( 'wp-oembed', "/wp-includes/js/wp-oembed$suffix.js" );
     470
    469471        // To enqueue media-views or media-editor, call wp_enqueue_media().
    470472        // Both rely on numerous settings, styles, and templates to operate correctly.
    471473        $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

     
    3939elseif ( is_trackback() ) :
    4040        include( ABSPATH . 'wp-trackback.php' );
    4141        return;
     42elseif ( 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;
    4256endif;
    4357
    4458if ( defined('WP_USE_THEMES') && WP_USE_THEMES ) :
  • src/wp-settings.php

     
    146146require( ABSPATH . WPINC . '/canonical.php' );
    147147require( ABSPATH . WPINC . '/shortcodes.php' );
    148148require( ABSPATH . WPINC . '/class-wp-embed.php' );
     149require( ABSPATH . WPINC . '/class-wp-oembed-controller.php' );
     150require( ABSPATH . WPINC . '/oembed-functions.php' );
    149151require( ABSPATH . WPINC . '/media.php' );
    150152require( ABSPATH . WPINC . '/http.php' );
    151153require( ABSPATH . WPINC . '/widgets.php' );
  • tests/phpunit/tests/oembed/controller.php

     
     1<?php
     2
     3/**
     4 * @group oembed
     5 */
     6class 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 */
     6class 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 */
     6class 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>
     40EOD;
     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 */
     6class Tests_oEmbed_Response_Data extends WP_UnitTestCase {
     7        function test_get_oembed_response_data_non_existent_post() {
     8                $this->assertFalse( get_oembed_response_data( 0, 100 ) );
     9        }
     10
     11        function test_get_oembed_response_data() {
     12                $post = $this->factory->post->create_and_get( array(
     13                        'post_title' => 'Some Post',
     14                ) );
     15
     16                $data = get_oembed_response_data( $post, 400 );
     17
     18                $this->assertEqualSets( array(
     19                        'version'       => '1.0',
     20                        'provider_name' => get_bloginfo( 'name' ),
     21                        'provider_url'  => get_home_url( '/' ),
     22                        'author_name'   => get_bloginfo( 'name' ),
     23                        'author_url'    => get_home_url( '/' ),
     24                        'title'         => 'Some Post',
     25                        'type'          => 'rich',
     26                        'width'         => 400,
     27                        'height'        => 225,
     28                        'html'          => get_post_embed_html( $post, 400, 225 ),
     29                ), $data );
     30        }
     31
     32        /**
     33         * Test get_oembed_response_data with an author.
     34         */
     35        function test_get_oembed_response_data_author() {
     36                $user_id = $this->factory->user->create( array(
     37                        'display_name' => 'John Doe',
     38                ) );
     39
     40                $post = $this->factory->post->create_and_get( array(
     41                        'post_title'  => 'Some Post',
     42                        'post_author' => $user_id,
     43                ) );
     44
     45                $data = get_oembed_response_data( $post, 400 );
     46
     47                $this->assertEqualSets( array(
     48                        'version'       => '1.0',
     49                        'provider_name' => get_bloginfo( 'name' ),
     50                        'provider_url'  => get_home_url( '/' ),
     51                        'author_name'   => 'John Doe',
     52                        'author_url'    => get_author_posts_url( $user_id ),
     53                        'title'         => 'Some Post',
     54                        'type'          => 'rich',
     55                        'width'         => 400,
     56                        'height'        => 225,
     57                        'html'          => get_post_embed_html( $post, 400, 225 ),
     58                ), $data );
     59        }
     60
     61        function test_get_oembed_response_link() {
     62                remove_filter( 'oembed_response_data', 'get_oembed_response_data_rich' );
     63
     64                $post = $this->factory->post->create_and_get( array(
     65                        'post_title' => 'Some Post',
     66                ) );
     67
     68                $data = get_oembed_response_data( $post, 600 );
     69
     70                $this->assertEqualSets( array(
     71                        'version'       => '1.0',
     72                        'provider_name' => get_bloginfo( 'name' ),
     73                        'provider_url'  => get_home_url( '/' ),
     74                        'author_name'   => get_bloginfo( 'name' ),
     75                        'author_url'    => get_home_url( '/' ),
     76                        'title'         => 'Some Post',
     77                        'type'          => 'link',
     78                ), $data );
     79
     80                add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
     81        }
     82
     83        function test_get_oembed_response_data_with_draft_post() {
     84                $post = $this->factory->post->create_and_get( array(
     85                        'post_status' => 'draft',
     86                ) );
     87
     88                $this->assertFalse( get_oembed_response_data( $post, 100 ) );
     89        }
     90
     91        function test_get_oembed_response_data_with_scheduled_post() {
     92                $post = $this->factory->post->create_and_get( array(
     93                        'post_status' => 'future',
     94                        'post_date'   => strftime( '%Y-%m-%d %H:%M:%S', strtotime( '+1 day' ) ),
     95                ) );
     96
     97                $this->assertFalse( get_oembed_response_data( $post, 100 ) );
     98        }
     99
     100        function test_get_oembed_response_data_with_private_post() {
     101                $post = $this->factory->post->create_and_get( array(
     102                        'post_status' => 'private',
     103                ) );
     104
     105                $this->assertFalse( get_oembed_response_data( $post, 100 ) );
     106        }
     107
     108        function test_get_oembed_response_data_maxwidth_too_high() {
     109                $post = $this->factory->post->create_and_get();
     110
     111                $data = get_oembed_response_data( $post, 1000 );
     112
     113                $this->assertEquals( 600, $data['width'] );
     114                $this->assertEquals( 338, $data['height'] );
     115        }
     116
     117        function test_get_oembed_response_data_maxwidth_too_low() {
     118                $post = $this->factory->post->create_and_get();
     119
     120                $data = get_oembed_response_data( $post, 100 );
     121
     122                $this->assertEquals( 200, $data['width'] );
     123                $this->assertEquals( 200, $data['height'] );
     124        }
     125
     126        function test_get_oembed_response_data_with_thumbnail() {
     127                $post          = $this->factory->post->create_and_get();
     128                $file          = DIR_TESTDATA . '/images/canola.jpg';
     129                $attachment_id = $this->factory->attachment->create_object( $file, $post->ID, array(
     130                        'post_mime_type' => 'image/jpeg',
     131                ) );
     132                set_post_thumbnail( $post, $attachment_id );
     133
     134                $data = get_oembed_response_data( $post, 400 );
     135
     136                $this->assertArrayHasKey( 'thumbnail_url', $data );
     137                $this->assertArrayHasKey( 'thumbnail_width', $data );
     138                $this->assertArrayHasKey( 'thumbnail_height', $data );
     139                $this->assertTrue( 400 >= $data['thumbnail_width'] );
     140        }
     141
     142        function test_get_oembed_response_data_for_attachment() {
     143                $parent = $this->factory->post->create();
     144                $file   = DIR_TESTDATA . '/images/canola.jpg';
     145                $post   = $this->factory->attachment->create_object( $file, $parent, array(
     146                        'post_mime_type' => 'image/jpeg',
     147                ) );
     148
     149                $data = get_oembed_response_data( $post, 400 );
     150
     151                $this->assertArrayHasKey( 'thumbnail_url', $data );
     152                $this->assertArrayHasKey( 'thumbnail_width', $data );
     153                $this->assertArrayHasKey( 'thumbnail_height', $data );
     154                $this->assertTrue( 400 >= $data['thumbnail_width'] );
     155        }
     156}
  • tests/phpunit/tests/oembed/headers.php

     
     1<?php
     2
     3/**
     4 * @runTestsInSeparateProcesses
     5 * @preserveGlobalState disabled
     6 * @group oembed
     7 */
     8class 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 */
     6class 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 */
     6class 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                        '&hellip; <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}