WordPress.org

Make WordPress Core

Ticket #32522: 32522.6.diff

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

     
    232232                                        'wp-includes/css/*.css',
    233233
    234234                                        // Exceptions
    235                                         '!wp-includes/css/dashicons.css'
     235                                        '!wp-includes/css/dashicons.css',
     236                                        '!wp-includes/css/wp-oembed-embed.css'
    236237                                ]
    237238                        },
    238239                        colors: {
     
    528529                        emoji: {
    529530                                src: BUILD_DIR + 'wp-includes/formatting.php',
    530531                                dest: '.'
     532                        },
     533                        oembed: {
     534                                src: BUILD_DIR + 'wp-includes/oembed-functions.php',
     535                                dest: '.'
    531536                        }
    532537                },
    533538                _watch: {
     
    637642                'clean:tinymce',
    638643                'concat:emoji',
    639644                'includes:emoji',
     645                'includes:oembed',
    640646                'jsvalidate:build'
    641647        ] );
    642648
  • 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/css/wp-oembed-embed.css

     
     1html, body {
     2        padding: 0;
     3        margin: 0;
     4}
     5
     6body {
     7        font-family: sans-serif;
     8}
     9
     10/* Text meant only for screen readers */
     11.screen-reader-text {
     12        clip: rect(1px, 1px, 1px, 1px);
     13        height: 1px;
     14        overflow: hidden;
     15        position: absolute !important;
     16        width: 1px;
     17}
     18
     19/* Dashicons */
     20.dashicons {
     21        display: inline-block;
     22        width: 20px;
     23        height: 20px;
     24        background-color: transparent;
     25        background-repeat: no-repeat;
     26        -webkit-background-size: 20px 20px;
     27        background-size: 20px;
     28        background-position: center;
     29        -webkit-transition: background .1s ease-in;
     30        transition: background .1s ease-in;
     31        position: relative;
     32        top: 5px;
     33}
     34
     35.dashicons-no {
     36        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M15.55%2013.7l-2.19%202.06-3.42-3.65-3.64%203.43-2.06-2.18%203.64-3.43-3.42-3.64%202.18-2.06%203.43%203.64%203.64-3.42%202.05%202.18-3.64%203.43z%27%20fill%3D%27%23fff%27%2F%3E%3C%2Fsvg%3E");
     37}
     38
     39.dashicons-admin-comments {
     40        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
     41}
     42
     43.wp-embed-comments a:hover .dashicons-admin-comments {
     44        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M5%202h9q.82%200%201.41.59T16%204v7q0%20.82-.59%201.41T14%2013h-2l-5%205v-5H5q-.82%200-1.41-.59T3%2011V4q0-.82.59-1.41T5%202z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
     45}
     46
     47.dashicons-share {
     48        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%2382878c%27%2F%3E%3C%2Fsvg%3E");
     49}
     50
     51.wp-embed-share-dialog-open:hover .dashicons-share {
     52        background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.5%2012q1.24%200%202.12.88T17.5%2015t-.88%202.12-2.12.88-2.12-.88T11.5%2015q0-.34.09-.69l-4.38-2.3Q6.32%2013%205%2013q-1.24%200-2.12-.88T2%2010t.88-2.12T5%207q1.3%200%202.21.99l4.38-2.3q-.09-.35-.09-.69%200-1.24.88-2.12T14.5%202t2.12.88T17.5%205t-.88%202.12T14.5%208q-1.3%200-2.21-.99l-4.38%202.3Q8%209.66%208%2010t-.09.69l4.38%202.3q.89-.99%202.21-.99z%27%20fill%3D%27%230073aa%27%2F%3E%3C%2Fsvg%3E");
     53}
     54
     55.wp-embed {
     56        width: 100%;
     57        padding: 25px;
     58        font: 400 14px/1.5 'Open Sans', sans-serif;
     59        color: #82878c;
     60        background: white;
     61        border: 1px solid #e5e5e5;
     62        -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
     63        box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
     64        -webkit-box-sizing: border-box;
     65        -moz-box-sizing: border-box;
     66        box-sizing: border-box;
     67        /* Clearfix */
     68        overflow: auto;
     69        zoom: 1;
     70}
     71
     72.wp-embed a {
     73        color: #82878c;
     74        text-decoration: none;
     75}
     76
     77.wp-embed a:hover {
     78        text-decoration: underline;
     79}
     80
     81.wp-embed-featured-image {
     82        margin-bottom: 20px;
     83}
     84
     85.wp-embed-featured-image img {
     86        width: 100%;
     87        height: auto;
     88        border: none;
     89}
     90
     91.wp-embed-featured-image.square {
     92        float: left;
     93        max-width: 160px;
     94        margin-right: 20px;
     95}
     96
     97.wp-embed p {
     98        margin: 0;
     99}
     100
     101p.wp-embed-heading {
     102        margin: 0 0 15px;
     103        font-weight: bold;
     104        font-size: 22px;
     105        line-height: 1.3;
     106}
     107
     108.wp-embed-heading a {
     109        color: #32373c;
     110}
     111
     112.wp-embed .wp-embed-more {
     113        color: #b4b9be;
     114}
     115
     116.wp-embed-footer {
     117        display: table;
     118        width: 100%;
     119        margin-top: 30px;
     120}
     121
     122.wp-embed-site-icon {
     123        position: absolute;
     124        top: 50%;
     125        left: 0;
     126        -webkit-transform: translateY(-50%);
     127        -ms-transform: translateY(-50%);
     128        transform: translateY(-50%);
     129        height: 25px;
     130        width: 25px;
     131        border: 0;
     132}
     133
     134.wp-embed-site-title {
     135        font-weight: bold;
     136        line-height: 25px;
     137}
     138
     139.wp-embed-site-title a {
     140        position: relative;
     141        display: inline-block;
     142        padding-left: 35px;
     143}
     144
     145.wp-embed-site-title,
     146.wp-embed-meta {
     147        display: table-cell;
     148}
     149
     150.wp-embed-meta {
     151        text-align: right;
     152        white-space: nowrap;
     153        vertical-align: middle;
     154}
     155
     156.wp-embed-comments,
     157.wp-embed-share {
     158        display: inline;
     159}
     160
     161.wp-embed-meta a:hover {
     162        text-decoration: none;
     163        color: #0073aa;
     164}
     165
     166.wp-embed-comments a {
     167        line-height: 25px;
     168        display: inline-block;
     169}
     170
     171.wp-embed-comments + .wp-embed-share {
     172        margin-left: 10px;
     173}
     174
     175.wp-embed-share-dialog {
     176        position: absolute;
     177        top: 0;
     178        left: 0;
     179        right: 0;
     180        bottom: 0;
     181        background-color: rgba(10, 10, 10, 0.9);
     182        color: #fff;
     183        opacity: 1;
     184        transition: opacity .25s ease-in-out;
     185        -moz-transition: opacity .25s ease-in-out;
     186        -webkit-transition: opacity .25s ease-in-out;
     187}
     188
     189.wp-embed-share-dialog.hidden {
     190        opacity: 0;
     191        visibility: hidden;
     192}
     193
     194.wp-embed-share-dialog-open,
     195.wp-embed-share-dialog-close {
     196        margin: -8px 0 0;
     197        padding: 0;
     198        background: transparent;
     199        border: none;
     200        cursor: pointer;
     201        outline: none;
     202}
     203
     204.wp-embed-share-dialog-open .dashicons,
     205.wp-embed-share-dialog-close .dashicons {
     206        padding: 4px;
     207}
     208
     209.wp-embed-share-dialog-open .dashicons {
     210        top: 8px;
     211}
     212
     213.wp-embed-share-dialog-open:focus .dashicons,
     214.wp-embed-share-dialog-close:focus .dashicons {
     215        -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
     216        box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8);
     217        -webkit-border-radius: 100%;
     218        border-radius: 100%;
     219}
     220
     221.wp-embed-share-dialog-close {
     222        position: absolute;
     223        top: 20px;
     224        right: 20px;
     225        font-size: 22px;
     226}
     227
     228.wp-embed-share-dialog-close:hover {
     229        text-decoration: none;
     230}
     231
     232.wp-embed-share-dialog-close .dashicons {
     233        height: 24px;
     234        width: 24px;
     235        -webkit-background-size: 24px 24px;
     236        background-size: 24px;
     237}
     238
     239.wp-embed-share-dialog-content {
     240        height: 100%;
     241        -webkit-transform-style: preserve-3d;
     242        transform-style: preserve-3d;
     243        overflow: hidden;
     244}
     245
     246.wp-embed-share-dialog-text {
     247        margin-top: 25px;
     248        padding: 20px;
     249}
     250
     251.wp-embed-share-tabs {
     252        margin: 0 0 20px;
     253        padding: 0;
     254        list-style: none;
     255}
     256
     257.wp-embed-share-tab-button {
     258        display: inline;
     259}
     260
     261.wp-embed-share-tab-button button {
     262        margin: 0;
     263        padding: 0;
     264        border: none;
     265        background: transparent;
     266        font-size: 16px;
     267        line-height: 1.3;
     268        color: #aaa;
     269        cursor: pointer;
     270        -webkit-transition: color .1s ease-in;
     271        transition: color .1s ease-in;
     272}
     273
     274.wp-embed-share-tab-button [aria-selected="true"] {
     275        color: #fff;
     276}
     277
     278.wp-embed-share-tab-button button:hover {
     279        color: #fff;
     280}
     281
     282.wp-embed-share-tab-button + .wp-embed-share-tab-button {
     283        margin: 0 0 0 10px;
     284        padding: 0 0 0 11px;
     285        border-left: 1px solid #aaa;
     286}
     287
     288.wp-embed-share-tab[aria-hidden="true"] {
     289        display: none;
     290}
     291
     292p.wp-embed-share-description {
     293        margin: 0;
     294        font-size: 14px;
     295        line-height: 1;
     296        font-style: italic;
     297        color: #aaa;
     298}
     299
     300.wp-embed-share-input {
     301        -webkit-box-sizing: border-box;
     302        -moz-box-sizing: border-box;
     303        box-sizing: border-box;
     304        width: 100%;
     305        border: none;
     306        height: 28px;
     307        margin: 0 0 10px 0;
     308        padding: 0 5px;
     309        font: 400 14px/1.5 'Open Sans', sans-serif;
     310        resize: none;
     311        cursor: text;
     312}
     313
     314textarea.wp-embed-share-input {
     315        height: 72px;
     316}
     317
     318html[dir="rtl"] .wp-embed-featured-image.square {
     319        float: right;
     320        margin-right: 0;
     321
     322        margin-left: 20px;
     323}
     324
     325html[dir="rtl"] .wp-embed-site-title a {
     326        padding-left: 0;
     327        padding-right: 35px;
     328}
     329
     330html[dir="rtl"] .wp-embed-site-icon {
     331        margin-right: 0;
     332        margin-left: 10px;
     333        left: auto;
     334        right: 0;
     335}
     336
     337html[dir="rtl"] .wp-embed-meta {
     338        text-align: left;
     339}
     340
     341html[dir="rtl"] .wp-embed-footer {
     342}
     343
     344html[dir="rtl"] .wp-embed-share {
     345        margin-left: 0;
     346        margin-right: 10px;
     347}
     348
     349html[dir="rtl"] .wp-embed-share-dialog-close {
     350        right: auto;
     351        left: 20px;
     352}
     353
     354html[dir="rtl"] .wp-embed-share-tab-button + .wp-embed-share-tab-button {
     355        margin: 0 10px 0 0;
     356        padding: 0 11px 0 0;
     357        border-left: none;
     358        border-right: 1px solid #aaa;
     359}
  • src/wp-includes/default-filters.php

     
    422422add_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 );
    423423add_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
    424424
     425// Embeds
     426
     427add_action( 'parse_query', 'wp_oembed_parse_query' );
     428
     429add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
     430add_action( 'wp_head', 'wp_oembed_add_host_js' );
     431
     432add_action( 'oembed_head', 'print_emoji_detection_script' );
     433add_action( 'oembed_head', 'print_emoji_styles' );
     434add_action( 'oembed_head', 'print_oembed_embed_styles' );
     435add_action( 'oembed_head', 'print_oembed_embed_scripts' );
     436add_action( 'oembed_head', 'wp_print_head_scripts', 20 );
     437add_action( 'oembed_head', 'wp_print_styles', 20 );
     438add_action( 'oembed_head', 'wp_no_robots' );
     439add_action( 'oembed_head', 'rel_canonical' );
     440add_action( 'oembed_head', 'locale_stylesheet' );
     441
     442add_action( 'oembed_footer', 'wp_print_footer_scripts', 20 );
     443
     444add_filter( 'excerpt_more', 'wp_oembed_excerpt_more', 20 );
     445add_filter( 'the_excerpt_embed', 'wptexturize' );
     446add_filter( 'the_excerpt_embed', 'convert_chars' );
     447add_filter( 'the_excerpt_embed', 'wpautop' );
     448add_filter( 'the_excerpt_embed', 'shortcode_unautop' );
     449add_filter( 'the_excerpt_embed', 'wp_oembed_excerpt_attachment' );
     450
     451add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 );
     452add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 );
     453
    425454unset( $filter, $action );
  • src/wp-includes/embed-functions.php

     
    326326         */
    327327        return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
    328328}
     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}
     793
     794/**
     795 * Print the CSS in the embed iframe header.
     796 *
     797 * @since 4.4.0
     798 */
     799function print_oembed_embed_styles() {
     800        ?>
     801        <style type="text/css">
     802        <?php
     803                if ( WP_DEBUG ) {
     804                        readfile( ABSPATH . WPINC . "/css/wp-oembed-embed.css" );
     805                } else {
     806                        /*
     807                         * If you're looking at a src version of this file, you'll see an "include"
     808                         * statement below. This is used by the `grunt build` process to directly
     809                         * include a minified version of wp-oembed-embed.css, instead of using the
     810                         * readfile() method from above.
     811                         *
     812                         * If you're looking at a build version of this file, you'll see a string of
     813                         * minified CSS. If you need to debug it, please turn on WP_DEBUG
     814                         * and edit wp-oembed-embed.css directly.
     815                         */
     816                        ?>
     817                        include "css/wp-oembed-embed.min.css"
     818                        <?php
     819                }
     820        ?>
     821        </style>
     822        <?php
     823}
     824
     825/**
     826 * Print the CSS in the embed iframe header.
     827 *
     828 * @since 4.4.0
     829 */
     830function print_oembed_embed_scripts() {
     831        ?>
     832        <script type="text/javascript">
     833        <?php
     834                if ( SCRIPT_DEBUG ) {
     835                        readfile( ABSPATH . WPINC . "/js/wp-oembed-embed.js" );
     836                } else {
     837                        /*
     838                         * If you're looking at a src version of this file, you'll see an "include"
     839                         * statement below. This is used by the `grunt build` process to directly
     840                         * include a minified version of wp-oembed-embed.js, instead of using the
     841                         * readfile() method from above.
     842                         *
     843                         * If you're looking at a build version of this file, you'll see a string of
     844                         * minified JavaScript. If you need to debug it, please turn on SCRIPT_DEBUG
     845                         * and edit wp-oembed-embed.js directly.
     846                         */
     847                        ?>
     848                        include "js/wp-oembed-embed.min.js"
     849                        <?php
     850                }
     851        ?>
     852        </script>
     853        <?php
     854}
     855 No newline at end of file
  • src/wp-includes/embed-template.php

     
     1<?php
     2/**
     3 * Contains the post embed template.
     4 *
     5 * When a post is embedded in an iframe, this file is used to
     6 * create the output.
     7 *
     8 * @package WordPress
     9 * @subpackage oEmbed
     10 * @since 4.4.0
     11 */
     12
     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        <?php
     26        /**
     27         * Print scripts or data in the embed template <head> tag.
     28         *
     29         * @since 4.4.0
     30         */
     31        do_action( 'oembed_head' );
     32        ?>
     33</head>
     34<body <?php body_class(); ?>>
     35<?php
     36if ( have_posts() ) :
     37        while ( have_posts() ) : the_post();
     38                // Add post thumbnail to response if available.
     39                $thumbnail_id = false;
     40
     41                if ( has_post_thumbnail() ) {
     42                        $thumbnail_id = get_post_thumbnail_id();
     43                }
     44
     45                if ( 'attachment' === get_post_type() && wp_attachment_is_image() ) {
     46                        $thumbnail_id = get_the_ID();
     47                }
     48
     49                if ( $thumbnail_id ) {
     50                        $aspect_ratio = 1;
     51                        $measurements = array( 1, 1 );
     52                        $image_size   = 'full'; // Fallback.
     53
     54                        $meta = wp_get_attachment_metadata( $thumbnail_id );
     55                        if ( is_array( $meta ) ) {
     56                                foreach ( $meta['sizes'] as $size => $data ) {
     57                                        if ( $data['width'] / $data['height'] > $aspect_ratio ) {
     58                                                $aspect_ratio = $data['width'] / $data['height'];
     59                                                $measurements = array( $data['width'], $data['height'] );
     60                                                $image_size   = $size;
     61                                        }
     62                                }
     63                        }
     64
     65                        /**
     66                         * Filter the thumbnail image size for use in the embed template.
     67                         *
     68                         * @param string $image_size Thumbnail image size.
     69                         */
     70                        $image_size = apply_filters( 'oembed_thumbnail_image_size', $image_size );
     71
     72                        $shape = $measurements[0] / $measurements[1] >= 1.75 ? 'rectangular' : 'square';
     73
     74                        /**
     75                         * Filter the thumbnail shape for use in the embed template.
     76                         *
     77                         * Rectangular images are shown above the title
     78                         * while square images are shown next to the content.
     79                         *
     80                         * @since 4.4.0
     81                         *
     82                         * @param string $shape Thumbnail image shape. Either 'rectangular' or 'square'.
     83                         */
     84                        $shape = apply_filters( 'oembed_thumbnail_image_shape', $shape );
     85                }
     86                ?>
     87                <div <?php post_class( 'wp-embed' ); ?>>
     88                        <?php if ( $thumbnail_id && 'rectangular' === $shape ) : ?>
     89                                <div class="wp-embed-featured-image rectangular">
     90                                        <a href="<?php the_permalink(); ?>" target="_top">
     91                                                <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?>
     92                                        </a>
     93                                </div>
     94                        <?php endif; ?>
     95
     96                        <p class="wp-embed-heading">
     97                                <a href="<?php the_permalink(); ?>" target="_top">
     98                                        <?php the_title(); ?>
     99                                </a>
     100                        </p>
     101
     102                        <?php if ( $thumbnail_id && 'square' === $shape ) : ?>
     103                                <div class="wp-embed-featured-image square">
     104                                        <a href="<?php the_permalink(); ?>" target="_top">
     105                                                <?php echo wp_get_attachment_image( $thumbnail_id, $image_size ); ?>
     106                                        </a>
     107                                </div>
     108                        <?php endif; ?>
     109
     110                        <div class="wp-embed-excerpt"><?php the_excerpt_embed(); ?></div>
     111
     112                        <?php
     113                        /**
     114                         * Print additional content after the embed excerpt.
     115                         *
     116                         * @since 4.4.0
     117                         */
     118                        do_action( 'oembed_content' );
     119                        ?>
     120
     121                        <div class="wp-embed-footer">
     122                                <div class="wp-embed-site-title">
     123                                        <?php
     124                                        $site_icon_url = admin_url( 'images/w-logo-blue.png' );
     125
     126                                        if ( function_exists( 'get_site_icon_url' ) ) {
     127                                                $site_icon_url = get_site_icon_url( 32, $site_icon_url );
     128                                        }
     129
     130                                        /**
     131                                         * Filters the site icon URL for use in the embed template.
     132                                         *
     133                                         * @param string $site_icon_url The site icon URL.
     134                                         */
     135                                        $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url );
     136
     137                                        printf(
     138                                                '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>',
     139                                                esc_url( home_url() ),
     140                                                esc_url( $site_icon_url ),
     141                                                esc_attr( get_bloginfo( 'name' ) )
     142                                        );
     143                                        ?>
     144                                </div>
     145
     146                                <div class="wp-embed-meta">
     147                                        <?php
     148                                        /**
     149                                         * Print additional meta content in the embed template.
     150                                         *
     151                                         * @since 4.4.0
     152                                         */
     153                                        do_action( 'oembed_content_meta');
     154                                        ?>
     155                                        <?php if ( get_comments_number() || comments_open() ) : ?>
     156                                                <div class="wp-embed-comments">
     157                                                        <a href="<?php comments_link(); ?>" target="_top">
     158                                                                <span class="dashicons dashicons-admin-comments"></span>
     159                                                                <?php
     160                                                                printf(
     161                                                                        _n(
     162                                                                                '%s <span class="screen-reader-text">Comment</span>',
     163                                                                                '%s <span class="screen-reader-text">Comments</span>',
     164                                                                                get_comments_number(),
     165                                                                                'oembed-api'
     166                                                                        ),
     167                                                                        absint( get_comments_number() )
     168                                                                );
     169                                                                ?>
     170                                                        </a>
     171                                                </div>
     172                                        <?php endif; ?>
     173                                        <div class="wp-embed-share">
     174                                                <button type="button" class="wp-embed-share-dialog-open"
     175                                                        aria-label="<?php esc_attr_e( 'Open sharing dialog', 'oembed-api' ); ?>">
     176                                                        <span class="dashicons dashicons-share"></span>
     177                                                </button>
     178                                        </div>
     179                                </div>
     180                        </div>
     181                        <div class="wp-embed-share-dialog hidden">
     182                                <div class="wp-embed-share-dialog-content">
     183                                        <div class="wp-embed-share-dialog-text">
     184                                                <ul class="wp-embed-share-tabs" role="tablist">
     185                                                        <li id="wp-embed-share-tab-button-wordpress" class="wp-embed-share-tab-button" role="presentation">
     186                                                                <button role="tab" aria-controls="wp-embed-share-tab-wordpress" aria-selected="true" tabindex="0"><?php esc_html_e( 'WordPress Embed', 'oembed-api' ); ?></button>
     187                                                        </li>
     188                                                        <li id="wp-embed-share-tab-button-embed" class="wp-embed-share-tab-button" role="presentation">
     189                                                                <button role="tab" aria-controls="wp-embed-share-tab-html" aria-selected="false" tabindex="-1"><?php esc_html_e( 'HTML Embed', 'oembed-api' ); ?></button>
     190                                                        </li>
     191                                                </ul>
     192                                                <div id="wp-embed-share-tab-wordpress" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-wordpress" aria-hidden="false">
     193                                                        <input type="text" value="<?php the_permalink(); ?>" class="wp-embed-share-input" tabindex="0" readonly/>
     194
     195                                                        <p class="wp-embed-share-description">
     196                                                                <?php _e( 'Copy and paste this URL into your WordPress site to embed', 'oembed-api' ); ?>
     197                                                        </p>
     198                                                </div>
     199                                                <div id="wp-embed-share-tab-html" class="wp-embed-share-tab" role="tabpanel" aria-labelledby="wp-embed-share-tab-button-html" aria-hidden="true">
     200                                                        <textarea class="wp-embed-share-input" tabindex="0" readonly><?php echo esc_attr( get_post_embed_html( null, 600, 400 ) ); ?></textarea>
     201
     202                                                        <p class="wp-embed-share-description">
     203                                                                <?php _e( 'Copy and paste this code into your site to embed', 'oembed-api' ); ?>
     204                                                        </p>
     205                                                </div>
     206                                        </div>
     207
     208                                        <button type="button" class="wp-embed-share-dialog-close" aria-label="<?php esc_attr_e( 'Close sharing dialog', 'oembed-api' ); ?>">
     209                                                <span class="dashicons dashicons-no"></span>
     210                                        </button>
     211                                </div>
     212                        </div>
     213                </div>
     214                <?php
     215        endwhile;
     216else :
     217        ?>
     218        <div class="wp-embed">
     219                <p class="wp-embed-heading"><?php _e( 'Page not found', 'oembed-api' ); ?></p>
     220
     221                <div class="wp-embed-excerpt">
     222                        <p><?php _e( 'Error 404! The requested content was not found.', 'oembed-api' ) ?></p>
     223                </div>
     224
     225                <div class="wp-embed-footer">
     226                        <div class="wp-embed-site-title">
     227                                <?php
     228                                $site_icon_url = admin_url( 'images/w-logo-blue.png' );
     229
     230                                if ( function_exists( 'get_site_icon_url' ) ) {
     231                                        $site_icon_url = get_site_icon_url( 32, $site_icon_url );
     232                                }
     233
     234                                /**
     235                                 * Filters the site icon URL for use in the embed template.
     236                                 *
     237                                 * @param string $site_icon_url The site icon URL.
     238                                 */
     239                                $site_icon_url = apply_filters( 'oembed_site_icon_url', $site_icon_url );
     240
     241                                printf(
     242                                        '<a href="%s" target="_top"><img src="%s" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>',
     243                                        esc_url( home_url() ),
     244                                        esc_url( $site_icon_url ),
     245                                        esc_attr( get_bloginfo( 'name' ) )
     246                                );
     247                                ?>
     248                        </div>
     249                </div>
     250        </div>
     251        <?php
     252endif;
     253
     254/**
     255 * Print scripts or data before the closing body tag in the embed template.
     256 *
     257 * @since 4.4.0
     258 */
     259do_action( 'oembed_footer' );
     260?>
     261</body>
     262</html>
  • src/wp-includes/js/tinymce/plugins/wpoembed/plugin.js

     
     1(function ( tinymce ) {
     2        'use strict';
     3
     4        tinymce.PluginManager.add( 'wpoembed', function ( editor, url ) {
     5                editor.on( 'init', function () {
     6                        var scriptId = editor.dom.uniqueId();
     7
     8                        var scriptElm = editor.dom.create( 'script', {
     9                                id: scriptId,
     10                                type: 'text/javascript',
     11                                src: url + '/../../../wp-oembed.js'
     12                        } );
     13
     14                        editor.getDoc().getElementsByTagName( 'head' )[ 0 ].appendChild( scriptElm );
     15                } );
     16        } );
     17})( window.tinymce );
  • src/wp-includes/js/wp-oembed-embed.js

     
     1(function ( window, document ) {
     2        'use strict';
     3
     4        var secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' ),
     5                resizing;
     6
     7        function sendEmbedMessage( message, value ) {
     8                window.parent.postMessage( {
     9                        message: message,
     10                        value: value,
     11                        secret: secret
     12                }, '*' );
     13        }
     14
     15        function onLoad() {
     16                var share_dialog = document.querySelector( '.wp-embed-share-dialog' ),
     17                        share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ),
     18                        share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ),
     19                        share_input = document.querySelectorAll( '.wp-embed-share-input' ),
     20                        share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ),
     21                        links = document.getElementsByTagName( 'a' ),
     22                        i;
     23
     24                if ( share_input ) {
     25                        for ( i = 0; i < share_input.length; i++ ) {
     26                                share_input[ i ].addEventListener( 'click', function ( e ) {
     27                                        e.target.select();
     28                                } );
     29                        }
     30                }
     31
     32                function openSharingDialog() {
     33                        share_dialog.className = share_dialog.className.replace( 'hidden', '' );
     34                        share_input[ 0 ].select();
     35                }
     36
     37                function closeSharingDialog() {
     38                        share_dialog.className += ' hidden';
     39                        document.querySelector( '.wp-embed-share-dialog-open' ).focus();
     40                }
     41
     42                if ( share_dialog_open ) {
     43                        share_dialog_open.addEventListener( 'click', function ( e ) {
     44                                openSharingDialog();
     45                                e.preventDefault();
     46                        } );
     47                }
     48
     49                if ( share_dialog_close ) {
     50                        share_dialog_close.addEventListener( 'click', function ( e ) {
     51                                closeSharingDialog();
     52                                e.preventDefault();
     53                        } );
     54                }
     55
     56                function shareClickHandler( e ) {
     57                        var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' );
     58                        currentTab.setAttribute( 'aria-selected', 'false' );
     59                        document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
     60
     61                        e.target.setAttribute( 'aria-selected', 'true' );
     62                        document.querySelector( '#' + e.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
     63                }
     64
     65                function shareKeyHandler( e ) {
     66                        var target = e.target,
     67                                previousSibling = target.parentElement.previousElementSibling,
     68                                nextSibling = target.parentElement.nextElementSibling,
     69                                newTab, newTabChild;
     70
     71                        if ( 37 === e.keyCode ) {
     72                                newTab = previousSibling;
     73                        } else if ( 39 === e.keyCode ) {
     74                                newTab = nextSibling;
     75                        } else {
     76                                return false;
     77                        }
     78
     79                        if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) {
     80                                newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling;
     81                        }
     82
     83                        if ( newTab ) {
     84                                newTabChild = newTab.firstElementChild;
     85
     86                                target.setAttribute( 'tabindex', '-1' );
     87                                target.setAttribute( 'aria-selected', false );
     88                                document.querySelector( '#' + target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' );
     89
     90                                newTabChild.setAttribute( 'tabindex', '0' );
     91                                newTabChild.setAttribute( 'aria-selected', 'true' );
     92                                newTabChild.focus();
     93                                document.querySelector( '#' + newTabChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' );
     94                        }
     95                }
     96
     97                if ( share_dialog_tabs ) {
     98                        for ( i = 0; i < share_dialog_tabs.length; i++ ) {
     99                                share_dialog_tabs[ i ].addEventListener( 'click', shareClickHandler );
     100
     101                                share_dialog_tabs[ i ].addEventListener( 'keydown', shareKeyHandler );
     102                        }
     103                }
     104
     105                document.addEventListener( 'keydown', function ( e ) {
     106                        if ( e.keyCode === 27 && -1 === share_dialog.className.indexOf( 'hidden' ) ) {
     107                                closeSharingDialog();
     108                        }
     109                }, false );
     110
     111                if ( window.self === window.top ) {
     112                        return;
     113                }
     114
     115                /**
     116                 * Send this document's height to the parent (embedding) site.
     117                 */
     118                sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
     119
     120                /**
     121                 * Detect clicks to external (_top) links.
     122                 */
     123                function linkClickHandler( e ) {
     124                        var target = e.target,
     125                                href;
     126                        if ( target.hasAttribute( 'href' ) ) {
     127                                href = target.getAttribute( 'href' );
     128                        } else {
     129                                href = target.parentElement.getAttribute( 'href' );
     130                        }
     131
     132                        /**
     133                         * Send link target to the parent (embedding) site.
     134                         */
     135                        sendEmbedMessage( 'link', href );
     136                        e.preventDefault();
     137                }
     138
     139                for ( i = 0; i < links.length; i++ ) {
     140                        links[ i ].addEventListener( 'click', linkClickHandler );
     141                }
     142        }
     143
     144        document.addEventListener( 'DOMContentLoaded', onLoad, false );
     145
     146        /**
     147         * Iframe resize handler.
     148         */
     149        function onResize() {
     150                if ( window.self === window.top ) {
     151                        return;
     152                }
     153
     154                clearTimeout( resizing );
     155
     156                resizing = setTimeout( function () {
     157                        sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) );
     158                }, 100 );
     159        }
     160
     161        window.addEventListener( 'resize', onResize, false );
     162})( window, document );
  • src/wp-includes/js/wp-oembed.js

     
     1(function ( window, document ) {
     2        'use strict';
     3
     4        window.wp = window.wp || {};
     5
     6        if ( !! window.wp.receiveEmbedMessage ) {
     7                return;
     8        }
     9
     10        window.wp.receiveEmbedMessage = function( e ) {
     11                var data = e.data;
     12                if ( ! ( data.secret || data.message || data.value ) ) {
     13                        return;
     14                }
     15
     16                var iframes = document.querySelectorAll( '.wp-embedded-content[data-secret="' + data.secret + '"]' );
     17
     18                for ( var i = 0; i < iframes.length; i++ ) {
     19                        var source = iframes[ i ];
     20
     21                        /* Resize the iframe on request. */
     22                        if ( 'height' === data.message ) {
     23                                var height = data.value;
     24                                if ( height > 1000 ) {
     25                                        height = 1000;
     26                                } else if ( height < 200 ) {
     27                                        height = 200;
     28                                }
     29
     30                                source.height = (height) + 'px';
     31                        }
     32
     33                        /* Link to a specific URL on request. */
     34                        if ( 'link' === data.message ) {
     35                                var sourceURL = document.createElement( 'a' ), targetURL = document.createElement( 'a' );
     36                                sourceURL.href = source.getAttribute( 'src' );
     37                                targetURL.href = data.value;
     38
     39                                /* Only continue if link hostname matches iframe's hostname. */
     40                                if ( targetURL.host === sourceURL.host && document.activeElement === source ) {
     41                                        window.top.location.href = data.value;
     42                                }
     43                        }
     44                }
     45        };
     46
     47        window.addEventListener( 'message', window.wp.receiveEmbedMessage, false );
     48
     49        function onLoad() {
     50                var isIE10 = -1 !== navigator.appVersion.indexOf( 'MSIE 10' ),
     51                        isIE11 = !!navigator.userAgent.match( /Trident.*rv\:11\./ );
     52
     53                /* Remove security attribute from iframes in IE10 and IE11. */
     54                if ( isIE10 || isIE11 ) {
     55                        var iframes = document.querySelectorAll( '.wp-embedded-content[security]' ), iframeClone;
     56
     57                        for ( var i = 0; i < iframes.length; i++ ) {
     58                                iframeClone = iframes[ i ].cloneNode( true );
     59                                iframeClone.removeAttribute( 'security' );
     60                                iframes[ i ].parentNode.insertBefore( iframeClone, iframes[ i ].nextSibling );
     61                                iframes[ i ].parentNode.removeChild( iframes[ i ] );
     62                        }
     63                }
     64        }
     65
     66        document.addEventListener( 'DOMContentLoaded', onLoad, false );
     67})( window, document );
  • src/wp-includes/query.php

     
    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

     
    147147require( ABSPATH . WPINC . '/shortcodes.php' );
    148148require( ABSPATH . WPINC . '/class-wp-embed.php' );
    149149require( ABSPATH . WPINC . '/embed-functions.php' );
     150require( ABSPATH . WPINC . '/class-wp-oembed-controller.php' );
    150151require( ABSPATH . WPINC . '/media.php' );
    151152require( ABSPATH . WPINC . '/http.php' );
    152153require( 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}