From 752708b84f9e5ed624ec6f293add923655dbee61 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Wed, 19 Oct 2016 09:28:22 +0000 Subject: [PATCH] Resource Hints: Allow passing custom attributes to resource hints. [37920] introduced resource hints that allow browsers to prefetch specific pages or render them in the background. With this change, the `as`, `crossorigin`, `pr`, and `type` attributes can be passed in addition to the URLs/hosts. Props peterwilsoncc, swissspidy. Fixes #38121. git-svn-id: https://develop.svn.wordpress.org/trunk@38826 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/general-template.php | 50 ++++++++++++++-- tests/phpunit/tests/general/resourceHints.php | 57 ++++++++++++++++++- 2 files changed, 100 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 23b2f1c5ab..5b36272270 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -2830,6 +2830,8 @@ function wp_resource_hints() { $hints['dns-prefetch'][] = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2.2.1/svg/' ); foreach ( $hints as $relation_type => $urls ) { + $unique_urls = array(); + /** * Filters domains and URLs for resource hints of relation type. * @@ -2841,16 +2843,31 @@ function wp_resource_hints() { $urls = apply_filters( 'wp_resource_hints', $urls, $relation_type ); foreach ( $urls as $key => $url ) { + $atts = array(); + + if ( is_array( $url ) ) { + if ( isset( $url['href'] ) ) { + $atts = $url; + $url = $url['href']; + } else { + continue; + } + } + $url = esc_url( $url, array( 'http', 'https' ) ); + if ( ! $url ) { - unset( $urls[ $key ] ); + continue; + } + + if ( isset( $unique_urls[ $url ] ) ) { continue; } if ( in_array( $relation_type, array( 'preconnect', 'dns-prefetch' ) ) ) { $parsed = wp_parse_url( $url ); + if ( empty( $parsed['host'] ) ) { - unset( $urls[ $key ] ); continue; } @@ -2862,13 +2879,34 @@ function wp_resource_hints() { } } - $urls[ $key ] = $url; + $atts['rel'] = $relation_type; + $atts['href'] = $url; + + $unique_urls[ $url ] = $atts; } - $urls = array_unique( $urls ); + foreach ( $unique_urls as $atts ) { + $html = ''; - foreach ( $urls as $url ) { - printf( "\n", $relation_type, $url ); + foreach ( $atts as $attr => $value ) { + if ( ! is_scalar( $value ) || + ( ! in_array( $attr, array( 'as', 'crossorigin', 'href', 'pr', 'rel', 'type' ), true ) && ! is_numeric( $attr )) + ) { + continue; + } + + $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value ); + + if ( ! is_string( $attr ) ) { + $html .= " $value"; + } else { + $html .= " $attr='$value'"; + } + } + + $html = trim( $html ); + + echo "\n"; } } } diff --git a/tests/phpunit/tests/general/resourceHints.php b/tests/phpunit/tests/general/resourceHints.php index a25d8bb07d..d7e30276f1 100644 --- a/tests/phpunit/tests/general/resourceHints.php +++ b/tests/phpunit/tests/general/resourceHints.php @@ -1,7 +1,7 @@ \n" . + "\n" . + "\n" . + "\n" . + "\n"; + + add_filter( 'wp_resource_hints', array( $this, '_add_url_with_attributes' ), 10, 2 ); + + $actual = get_echo( 'wp_resource_hints' ); + + remove_filter( 'wp_resource_hints', array( $this, '_add_url_with_attributes' ) ); + + $this->assertEquals( $expected, $actual ); + } + + function _add_url_with_attributes( $hints, $method ) { + // Ignore hints with missing href attributes. + $hints[] = array( + 'rel' => 'foo', + ); + + if ( 'preconnect' === $method ) { + // Should ignore rel attributes. + $hints[] = array( + 'rel' => 'foo', + 'href' => 'https://make.wordpress.org/great-again', + ); + } elseif ( 'prefetch' === $method ) { + $hints[] = array( + 'crossorigin', + 'as' => 'image', + 'pr' => 0.5, + 'href' => 'https://example.com/foo.jpeg', + ); + $hints[] = array( + 'crossorigin' => 'use-credentials', + 'as' => 'style', + 'href' => 'https://example.com/foo.css', + ); + } elseif ( 'prerender' === $method ) { + // Ignore invalid attributes. + $hints[] = array( + 'foo' => 'bar', + 'bar' => 'baz', + 'href' => 'http://wordpress.org', + ); + } + + return $hints; + } }