Make WordPress Core

Changeset 61119


Ignore:
Timestamp:
11/04/2025 12:45:02 AM (4 months ago)
Author:
westonruter
Message:

Embeds: Add wp_oembed_add_discovery_links() to run earlier at wp_head priority 4.

This results in the oEmbed discovery links being printed before scripts and styles are printed. This helps ensure they appear within the first 150K bytes of the HTML response, which is required by WP_oEmbed::discover(). With increasing the styles_inline_size_limit from 20K to 40K in #63018, it becomes more probable that the oEmbed discovery links will be pushed out of range.

For backwards compatibility with themes and plugins that disable the oEmbed discovery links by unhooking wp_oembed_add_discovery_links() from running at wp_head priority 10 (even though the oembed_discovery_links filter is available to disable such links), this callback is added a second time to run earlier at priority 4. The first time the function runs, it checks to see if the callback is still hooked at priority 10. If not, the function short circuits. If it is still hooked at priority 10, however, the function then unhooks itself at priority 10 so that it won't run a second time later during the wp_head action, before proceeding with printing the discovery links. A similar back-compat approach was taken previously in [60910]. The back-compat checks are only performed if the function is invoked during the wp_head action, allowing the function to be called "idempotently" elsewhere.

Developed in https://github.com/WordPress/wordpress-develop/pull/10449

Follow-up to [61118], [61117].

Props westonruter, swissspidy.
See #64186, #63018.
Fixes #64178.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/default-filters.php

    r61111 r61119  
    705705add_filter( 'rest_pre_serve_request', '_oembed_rest_pre_serve_request', 10, 4 );
    706706
    707 add_action( 'wp_head', 'wp_oembed_add_discovery_links' );
     707add_action( 'wp_head', 'wp_oembed_add_discovery_links', 4 ); // Printed after feed_links() and feed_links_extra().
     708add_action( 'wp_head', 'wp_oembed_add_discovery_links' ); // Unhooked the first time that wp_oembed_add_discovery_links() runs for back-compat.
    708709add_action( 'wp_head', 'wp_oembed_add_host_js' ); // Back-compat for sites disabling oEmbed host JS by removing action.
    709710add_filter( 'embed_oembed_html', 'wp_maybe_enqueue_oembed_host_js' );
  • trunk/src/wp-includes/embed.php

    r60948 r61119  
    333333 * @since 4.4.0
    334334 * @since 6.8.0 Output was adjusted to only embed if the post supports it.
     335 * @since 6.9.0 Now runs first at `wp_head` priority 4, with a fallback to priority 10. This helps ensure the discovery links appear within the first 150KB.
    335336 */
    336337function wp_oembed_add_discovery_links() {
     338    if ( doing_action( 'wp_head' ) ) {
     339        // For back-compat, short-circuit if a plugin has removed the action at the original priority.
     340        if ( ! has_action( 'wp_head', 'wp_oembed_add_discovery_links', 10 ) ) {
     341            return;
     342        }
     343
     344        // Prevent running again at the original priority.
     345        remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
     346    }
     347
    337348    $output = '';
    338349
  • trunk/tests/phpunit/tests/oembed/discovery.php

    r59700 r61119  
    5050
    5151        $this->assertSame( $expected, get_echo( 'wp_oembed_add_discovery_links' ) );
     52
     53        add_filter( 'oembed_discovery_links', '__return_empty_string' );
     54        $this->assertSame( '', get_echo( 'wp_oembed_add_discovery_links' ), 'Expected filtering oembed_discovery_links to empty string to result in no wp_oembed_add_discovery_links() output.' );
    5255    }
    5356
     
    101104        $this->assertFalse( get_oembed_response_data( $post, 100 ) );
    102105    }
     106
     107    /**
     108     * @ticket 64178
     109     * @covers ::wp_oembed_add_discovery_links
     110     */
     111    public function test_wp_oembed_add_discovery_links_back_compat() {
     112        $action       = 'wp_head';
     113        $old_priority = 10;
     114        $new_priority = 4;
     115        $callback     = 'wp_oembed_add_discovery_links';
     116
     117        $this->assertTrue( has_action( $action, $callback, $old_priority ), 'Expected wp_oembed_add_discovery_links() to be hooked at wp_head with old priority.' );
     118        $this->assertTrue( has_action( $action, $callback, $new_priority ), 'Expected wp_oembed_add_discovery_links() to be hooked at wp_head with new priority.' );
     119
     120        // Remove all wp_head actions and re-add just the one being tested.
     121        remove_all_actions( $action );
     122        add_action( $action, $callback, $old_priority );
     123        add_action( $action, $callback, $new_priority );
     124
     125        $post_id = self::factory()->post->create();
     126        $this->go_to( get_permalink( $post_id ) );
     127        $this->assertQueryTrue( 'is_single', 'is_singular' );
     128
     129        $mock_action = new MockAction();
     130        add_filter( 'oembed_discovery_links', array( $mock_action, 'filter' ) );
     131
     132        $wp_head_output = get_echo( 'wp_head' );
     133        $this->assertSame( 1, $mock_action->get_call_count() );
     134
     135        $expected  = '<link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink() ) ) . '" />' . "\n";
     136        $expected .= '<link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( get_permalink(), 'xml' ) ) . '" />' . "\n";
     137
     138        $this->assertSame( $expected, $wp_head_output, 'Expected wp_head output to be the same as the wp_oembed_add_discovery_links() output.' );
     139        $this->assertSame( $expected, get_echo( $callback ), 'Expected wp_oembed_add_discovery_links() output to be the same as the wp_head output when called outside of wp_head.' );
     140    }
    103141}
Note: See TracChangeset for help on using the changeset viewer.