diff --git src/wp-includes/embed.php src/wp-includes/embed.php index 8c79cc8..304bc3d 100644 --- src/wp-includes/embed.php +++ src/wp-includes/embed.php @@ -341,11 +341,12 @@ function wp_oembed_register_route() { * Adds oEmbed discovery links in the website
. * * @since 4.4.0 + * @since x.x.x Output was adjusted to only embed if the post supports it. */ function wp_oembed_add_discovery_links() { $output = ''; - if ( is_singular() ) { + if ( is_singular() && is_post_embeddable() ) { $output .= '' . "\n"; if ( class_exists( 'SimpleXMLElement' ) ) { @@ -510,10 +511,11 @@ JS; * Retrieves the oEmbed response data for a given post. * * @since 4.4.0 + * @since x.x.x Output was adjusted to only embed if the post type supports it. * - * @param WP_Post|int $post Post object or ID. - * @param int $width The requested width. - * @return array|false Response data on success, false if post doesn't exist. + * @param WP_Post|int $post Post object or ID. + * @param int $width The requested width. + * @return array|false Response data on success, false if post doesn't exist, or if post is not embeddable. */ function get_oembed_response_data( $post, $width ) { $post = get_post( $post ); @@ -526,6 +528,10 @@ function get_oembed_response_data( $post, $width ) { return false; } + if ( ! is_post_embeddable( $post ) ) { + return false; + } + /** * Filter the allowed minimum and maximum widths for the oEmbed response. * diff --git src/wp-includes/post.php src/wp-includes/post.php index be08ae3..74ae1e2 100644 --- src/wp-includes/post.php +++ src/wp-includes/post.php @@ -890,6 +890,7 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) * @since 2.9.0 * @since 3.0.0 The `show_ui` argument is now enforced on the new post screen. * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing screen and post editing screen. + * @since x.x.x Introduced the `is_embeddable` argument. * * @global array $wp_post_types List of post types. * @global WP_Rewrite $wp_rewrite Used for default feeds. @@ -962,6 +963,8 @@ function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) * @type bool|string $has_archive Whether there should be post type archives, or if a string, the * archive slug to use. Will generate the proper rewrite rules if * $rewrite is enabled. Default false. + * @type bool $is_embeddable Whether this post type should be embeddable through oEmbed. + * Default is value of `$public`. * @type bool|array $rewrite { * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. * Defaults to true, using $post_type as slug. To specify rewrite rules, an array can be @@ -1039,6 +1042,7 @@ function register_post_type( $post_type, $args = array() ) { 'register_meta_box_cb' => null, 'taxonomies' => array(), 'has_archive' => false, + 'is_embeddable' => null, 'rewrite' => true, 'query_var' => true, 'can_export' => true, @@ -1163,6 +1167,11 @@ function register_post_type( $post_type, $args = array() ) { add_permastruct( $post_type, "{$args->rewrite['slug']}/%$post_type%", $permastruct_args ); } + // If not set, default to the setting for public. + if ( null === $args->is_embeddable ) { + $args->is_embeddable = $args->public; + } + // Register the post type meta box if a custom callback was specified. if ( $args->register_meta_box_cb ) add_action( 'add_meta_boxes_' . $post_type, $args->register_meta_box_cb, 10, 1 ); @@ -1709,6 +1718,40 @@ function is_post_type_viewable( $post_type ) { } /** + * Determines whether a post is considered "embeddable". + * + * The 'is_embeddable' value of the post's type will be evaluated. + * + * @since x.x.x + * + * @param int|WP_Post|null $post Optional. Post ID or `WP_Post` object. Defaults to global $post. + * @return bool Whether the post should be considered embeddable. + */ +function is_post_embeddable( $post = null ) { + $post = get_post( $post ); + + if ( ! $post ) { + return false; + } + + $is_embeddable = false; + + if ( $post_type = get_post_type_object( $post->post_type ) ) { + $is_embeddable = $post_type->is_embeddable; + } + + /** + * Filter whether a post is embeddable. + * + * @since x.x.x + * + * @param bool $is_embeddable Whether the post is embeddable. + * @param WP_Post $post Post object. + */ + return apply_filters( 'is_post_embeddable', $is_embeddable, $post ); +} + +/** * Retrieve list of latest posts or posts matching criteria. * * The defaults are as follows: diff --git tests/phpunit/tests/oembed/discovery.php tests/phpunit/tests/oembed/discovery.php index d3fbab8..e43c2eb 100644 --- tests/phpunit/tests/oembed/discovery.php +++ tests/phpunit/tests/oembed/discovery.php @@ -71,4 +71,19 @@ class Tests_oEmbed_Discovery extends WP_UnitTestCase { $this->assertEquals( $expected, get_echo( 'wp_oembed_add_discovery_links' ) ); } + + /** + * @ticket 35567 + */ + function test_wp_oembed_add_discovery_links_non_embeddable_post_type_output_should_be_empty() { + register_post_type( 'not_embeddable', array( 'is_embeddable' => false ) ); + + $post = $this->factory()->post->create_and_get( array( + 'post_type' => 'not_embeddable' + ) ); + + $this->go_to( get_permalink( $post->ID ) ); + + $this->assertEmpty( wp_oembed_add_discovery_links() ); + } } diff --git tests/phpunit/tests/oembed/getResponseData.php tests/phpunit/tests/oembed/getResponseData.php index 4a5c4f7..0ad9438 100644 --- tests/phpunit/tests/oembed/getResponseData.php +++ tests/phpunit/tests/oembed/getResponseData.php @@ -167,4 +167,17 @@ class Tests_oEmbed_Response_Data extends WP_UnitTestCase { $this->assertArrayHasKey( 'thumbnail_height', $data ); $this->assertTrue( 400 >= $data['thumbnail_width'] ); } + + /** + * @ticket 35567 + */ + function test_get_oembed_response_data_non_embeddable_post_type_should_return_false() { + register_post_type( 'not_emebeddable', array( 'is_embeddable' => false ) ); + + $post = self::factory()->post->create_and_get( array( + 'post_type' => 'not_embeddable' + ) ); + + $this->assertFalse( get_oembed_response_data( $post, 100 ) ); + } } diff --git tests/phpunit/tests/oembed/template.php tests/phpunit/tests/oembed/template.php index 21fd485..c3b6116 100644 --- tests/phpunit/tests/oembed/template.php +++ tests/phpunit/tests/oembed/template.php @@ -301,4 +301,64 @@ class Tests_Embed_Template extends WP_UnitTestCase { $this->assertNotContains( '&', file_get_contents( $file ) ); } + /** + * @ticket 35567 + */ + public function test_is_embeddable_post_non_existent_post() { + $this->assertFalse( is_post_embeddable( 0 ) ); + } + + /** + * @ticket 35567 + */ + public function test_is_embeddable_post_non_existent_post_type() { + $post = self::factory()->post->create_and_get( array( + 'post_type' => rand_str(), + ) ); + + $this->assertFalse( is_post_embeddable( $post ) ); + } + + /** + * @ticket 35567 + */ + public function test_is_embeddable_post_should_return_false_for_non_embeddable_post_type() { + register_post_type( 'not_emebeddable', array( 'is_embeddable' => false ) ); + + $post = self::factory()->post->create_and_get( array( + 'post_type' => 'not_embeddable', + ) ); + + $this->assertFalse( is_post_embeddable( $post ) ); + } + + /** + * @ticket 35567 + */ + public function test_is_embeddable_post_should_return_true_for_embeddable_post_type() { + register_post_type( 'not_emebeddable', array( 'is_embeddable' => true ) ); + + $post = self::factory()->post->create_and_get( array( + 'post_type' => 'not_embeddable', + ) ); + + $this->assertFalse( is_post_embeddable( $post ) ); + } + + /** + * @ticket 35567 + */ + public function test_is_embeddable_post_filtered() { + register_post_type( 'not_emebeddable', array( 'is_embeddable' => false ) ); + + $post = self::factory()->post->create_and_get( array( + 'post_type' => 'not_embeddable', + ) ); + + add_filter( 'is_post_embeddable', '__return_true' ); + $is_embeddable = is_post_embeddable( $post ); + remove_filter( 'is_post_embeddable', '__return_true' ); + + $this->assertTrue( $is_embeddable ); + } } diff --git tests/phpunit/tests/post/types.php tests/phpunit/tests/post/types.php index 9cf44c8..da26008 100644 --- tests/phpunit/tests/post/types.php +++ tests/phpunit/tests/post/types.php @@ -428,4 +428,28 @@ class Tests_Post_Types extends WP_UnitTestCase { public function test_get_post_types_by_support_non_existant_feature() { $this->assertEqualSets( array(), get_post_types_by_support( 'somefeature' ) ); } + + /** + * @group oembed + * @ticket 35567 + */ + public function test_register_post_type_is_embeddable_defaults_to_public_argument() { + $post_type = register_post_type( rand_str( 10) ); + $this->assertFalse( $post_type->is_embeddable ); + + $post_type = register_post_type( rand_str( 10 ), array( 'public' => true ) ); + $this->assertTrue( $post_type->is_embeddable ); + } + + /** + * @group oembed + * @ticket 35567 + */ + public function test_register_post_type_override_is_embeddable() { + $post_type = register_post_type( rand_str( 10 ), array( 'is_embeddable' => true ) ); + $this->assertTrue( $post_type->is_embeddable ); + + $post_type = register_post_type( rand_str( 10 ), array( 'public' => true, 'is_embeddable' => false ) ); + $this->assertFalse( $post_type->is_embeddable ); + } }