From b2671c38801b19e99b62da459acfa4d7097d9c5f Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 15 Jun 2016 11:22:52 +0000 Subject: [PATCH] Embeds: Improve performance when embedding a post from the current site. When the post being embedded is from the same site, there's no reason to do an HTTP request for it. The data can be fetched directly using `get_oembed_response_data()`. Fixes #36767 for trunk. git-svn-id: https://develop.svn.wordpress.org/trunk@37708 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class-oembed.php | 24 ++++++++++- src/wp-includes/default-filters.php | 1 + src/wp-includes/embed.php | 32 ++++++++++++++ tests/phpunit/tests/oembed/wpOembed.php | 56 +++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tests/phpunit/tests/oembed/wpOembed.php diff --git a/src/wp-includes/class-oembed.php b/src/wp-includes/class-oembed.php index ef36683bc0..6bdc925e63 100644 --- a/src/wp-includes/class-oembed.php +++ b/src/wp-includes/class-oembed.php @@ -315,10 +315,32 @@ class WP_oEmbed { * @return false|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed. */ public function get_html( $url, $args = '' ) { + /** + * Filters the oEmbed result before any HTTP requests are made. + * + * This allows one to short-circuit the default logic, perhaps by + * replacing it with a routine that is more optimal for your setup. + * + * Passing a non-null value to the filter will effectively short-circuit retrieval, + * returning the passed value instead. + * + * @since 4.5.3 + * + * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. + * @param string $url The URL to the content that should be attempted to be embedded. + * @param array $args Optional. Arguments, usually passed from a shortcode. Default empty. + */ + $pre = apply_filters( 'pre_oembed_result', null, $url, $args ); + + if ( null !== $pre ) { + return $pre; + } + $provider = $this->get_provider( $url, $args ); - if ( !$provider || false === $data = $this->fetch( $provider, $url, $args ) ) + if ( ! $provider || false === $data = $this->fetch( $provider, $url, $args ) ) { return false; + } /** * Filters the HTML returned by the oEmbed provider. diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index f7bfeb52fb..ddaa5efe24 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -476,5 +476,6 @@ add_filter( 'the_excerpt_embed', 'wp_embed_excerpt_attachment' ); add_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10, 3 ); add_filter( 'oembed_response_data', 'get_oembed_response_data_rich', 10, 4 ); +add_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10, 3 ); unset( $filter, $action ); diff --git a/src/wp-includes/embed.php b/src/wp-includes/embed.php index 79b0503180..785b5f3a20 100644 --- a/src/wp-includes/embed.php +++ b/src/wp-includes/embed.php @@ -1079,3 +1079,35 @@ function the_embed_site_title() { */ echo apply_filters( 'embed_site_title_html', $site_title ); } + +/** + * Filters the oEmbed result before any HTTP requests are made. + * + * If the URL belongs to the current site, the result is fetched directly instead of + * going through the oEmbed discovery process. + * + * @since 4.5.3 + * + * @param null|string $result The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. Default null. + * @param string $url The URL that should be inspected for discovery `` tags. + * @param array $args oEmbed remote get arguments. + * @return null|string The UNSANITIZED (and potentially unsafe) HTML that should be used to embed. + * Null if the URL does not belong to the current site. + */ +function wp_filter_pre_oembed_result( $result, $url, $args ) { + $post_id = url_to_postid( $url ); + + /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ + $post_id = apply_filters( 'oembed_request_post_id', $post_id, $url ); + + $width = isset( $args['width'] ) ? $args['width'] : 0; + + $data = get_oembed_response_data( $post_id, $width ); + $data = _wp_oembed_get_object()->data2html( (object) $data, $url ); + + if ( ! $data ) { + return $result; + } + + return $data; +} diff --git a/tests/phpunit/tests/oembed/wpOembed.php b/tests/phpunit/tests/oembed/wpOembed.php new file mode 100644 index 0000000000..93a9cca77f --- /dev/null +++ b/tests/phpunit/tests/oembed/wpOembed.php @@ -0,0 +1,56 @@ +oembed = _wp_oembed_get_object(); + + $this->pre_oembed_result_filtered = false; + } + + public function _filter_pre_oembed_result( $result ) { + // If this is not null, the oEmbed result has been filtered before any HTTP requests were made. + $this->pre_oembed_result_filtered = $result; + + return $result; + } + + public function test_wp_filter_pre_oembed_result_prevents_http_request_for_internal_permalinks() { + $post_id = self::factory()->post->create(); + $permalink = get_permalink( $post_id ); + + add_filter( 'pre_oembed_result', array( $this, '_filter_pre_oembed_result' ) ); + $actual = $this->oembed->get_html( $permalink ); + remove_filter( 'pre_oembed_result', array( $this, '_filter_pre_oembed_result' ) ); + + $this->assertNotFalse( $this->pre_oembed_result_filtered ); + $this->assertEquals( $this->pre_oembed_result_filtered, $actual ); + } + + public function test_wp_filter_pre_oembed_result_prevents_http_request_when_viewing_the_post() { + $post_id = self::factory()->post->create(); + $permalink = get_permalink( $post_id ); + + $this->go_to( $permalink ); + $this->assertQueryTrue( 'is_single', 'is_singular' ); + + add_filter( 'pre_oembed_result', array( $this, '_filter_pre_oembed_result' ) ); + $actual = $this->oembed->get_html( $permalink ); + remove_filter( 'pre_oembed_result', array( $this, '_filter_pre_oembed_result' ) ); + + $this->assertNotFalse( $this->pre_oembed_result_filtered ); + $this->assertEquals( $this->pre_oembed_result_filtered, $actual ); + } +}