Make WordPress Core

Changeset 34903


Ignore:
Timestamp:
10/07/2015 10:35:18 AM (11 years ago)
Author:
pento
Message:

Embeds: Add oEmbed provider support.

For the past 6 years, WordPress has operated as an oEmbed consumer, allowing users to easily embed content from other sites. By adding oEmbed provider support, this allows any oEmbed consumer to embed posts from WordPress sites.

In addition to creating an oEmbed provider, WordPress' oEmbed consumer code has been enhanced to work with any site that provides oEmbed data (as long as it matches some strict security rules), and provides a preview from within the post editor.

For security, embeds appear within a sandboxed iframe - the iframe content is a template that can be styled or replaced entirely by the theme on the provider site.

Props swissspidy, pento, melchoyce, netweb, pfefferle, johnbillion, extendwings, davidbinda, danielbachhuber, SergeyBiryukov, afercia

Fixes #32522.

Location:
trunk
Files:
15 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Gruntfile.js

    r34888 r34903  
    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                        },
    … …  
    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                },
    … …  
    638643                'concat:emoji',
    639644                'includes:emoji',
     645                'includes:oembed',
    640646                'jsvalidate:build'
    641647        ] );
  • trunk/src/wp-includes/admin-bar.php

    r34348 r34903  
    899899                return false;
    900900
     901        if ( is_embed() ) {
     902                return false;
     903        }
     904
    901905        // Integrated into the admin.
    902906        if ( is_admin() )
  • trunk/src/wp-includes/class-wp-editor.php

    r34717 r34903  
    402402                                                'wpdialogs',
    403403                                                'wptextpattern',
    404                                                 'wpview'
     404                                                'wpview',
     405                                                'wpoembed',
    405406                                        );
    406407
  • trunk/src/wp-includes/class-wp-embed.php

    r33734 r34903  
    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
  • trunk/src/wp-includes/class-wp-rewrite.php

    r34708 r34903  
    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
    … …  
    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
    … …  
    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);
    … …  
    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:
    … …  
    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
    … …  
    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
    … …  
    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)
  • trunk/src/wp-includes/class-wp.php

    r34635 r34903  
    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        /**
  • trunk/src/wp-includes/default-filters.php

    r34855 r34903  
    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 );
  • trunk/src/wp-includes/embed-functions.php

    r34851 r34903  
    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}
  • trunk/src/wp-includes/query.php

    r34836 r34903  
    717717
    718718        return $wp_query->is_404();
     719}
     720
     721/**
     722 * Is the query for an embedded post?
     723 *
     724 * @since 4.4.0
     725 *
     726 * @global WP_Query $wp_query Global WP_Query instance.
     727 *
     728 * @return bool Whether we're in an embedded post or not.
     729 */
     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();
    719739}
    720740
    … …  
    12001220         */
    12011221        public $is_404 = false;
     1222
     1223        /**
     1224         * Set if query is embed.
     1225         *
     1226         * @since 4.4.0
     1227         * @access public
     1228         * @var bool
     1229         */
     1230        public $is_embed = false;
    12021231
    12031232        /**
    … …  
    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;
    … …  
    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         *
    … …  
    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.
  • trunk/src/wp-includes/script-loader.php

    r34869 r34903  
    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.
  • trunk/src/wp-includes/template-loader.php

    r32846 r34903  
    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
  • trunk/src/wp-settings.php

    r34853 r34903  
    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' );
  • trunk/tests/phpunit/multisite.xml

    r34656 r34903  
    2626            <group>ms-files</group>
    2727            <group>external-http</group>
     28            <group>oembed-headers</group>
    2829        </exclude>
    2930    </groups>
Note: See TracChangeset for help on using the changeset viewer.