[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Speculative loading functions. 4 * 5 * @package WordPress 6 * @subpackage Speculative Loading 7 * @since 6.8.0 8 */ 9 10 /** 11 * Returns the speculation rules configuration. 12 * 13 * @since 6.8.0 14 * 15 * @return array<string, string>|null Associative array with 'mode' and 'eagerness' keys, or null if speculative 16 * loading is disabled. 17 */ 18 function wp_get_speculation_rules_configuration(): ?array { 19 // By default, speculative loading is only enabled for sites with pretty permalinks when no user is logged in. 20 if ( ! is_user_logged_in() && get_option( 'permalink_structure' ) ) { 21 $config = array( 22 'mode' => 'auto', 23 'eagerness' => 'auto', 24 ); 25 } else { 26 $config = null; 27 } 28 29 /** 30 * Filters the way that speculation rules are configured. 31 * 32 * The Speculation Rules API is a web API that allows to automatically prefetch or prerender certain URLs on the 33 * page, which can lead to near-instant page load times. This is also referred to as speculative loading. 34 * 35 * There are two aspects to the configuration: 36 * * The "mode" (whether to "prefetch" or "prerender" URLs). 37 * * The "eagerness" (whether to speculatively load URLs in an "eager", "moderate", or "conservative" way). 38 * 39 * By default, the speculation rules configuration is decided by WordPress Core ("auto"). This filter can be used 40 * to force a certain configuration, which could for instance load URLs more or less eagerly. 41 * 42 * For logged-in users or for sites that are not configured to use pretty permalinks, the default value is `null`, 43 * indicating that speculative loading is entirely disabled. 44 * 45 * @since 6.8.0 46 * @see https://developer.chrome.com/docs/web-platform/prerender-pages 47 * 48 * @param array<string, string>|null $config Associative array with 'mode' and 'eagerness' keys, or `null`. The 49 * default value for both of the keys is 'auto'. Other possible values 50 * for 'mode' are 'prefetch' and 'prerender'. Other possible values for 51 * 'eagerness' are 'eager', 'moderate', and 'conservative'. The value 52 * `null` is used to disable speculative loading entirely. 53 */ 54 $config = apply_filters( 'wp_speculation_rules_configuration', $config ); 55 56 // Allow the value `null` to indicate that speculative loading is disabled. 57 if ( null === $config ) { 58 return null; 59 } 60 61 // Sanitize the configuration and replace 'auto' with current defaults. 62 $default_mode = 'prefetch'; 63 $default_eagerness = 'conservative'; 64 if ( ! is_array( $config ) ) { 65 return array( 66 'mode' => $default_mode, 67 'eagerness' => $default_eagerness, 68 ); 69 } 70 if ( 71 ! isset( $config['mode'] ) || 72 'auto' === $config['mode'] || 73 ! WP_Speculation_Rules::is_valid_mode( $config['mode'] ) 74 ) { 75 $config['mode'] = $default_mode; 76 } 77 if ( 78 ! isset( $config['eagerness'] ) || 79 'auto' === $config['eagerness'] || 80 ! WP_Speculation_Rules::is_valid_eagerness( $config['eagerness'] ) || 81 // 'immediate' is a valid eagerness, but for safety WordPress does not allow it for document-level rules. 82 'immediate' === $config['eagerness'] 83 ) { 84 $config['eagerness'] = $default_eagerness; 85 } 86 87 return array( 88 'mode' => $config['mode'], 89 'eagerness' => $config['eagerness'], 90 ); 91 } 92 93 /** 94 * Returns the full speculation rules data based on the configuration. 95 * 96 * Plugins with features that rely on frontend URLs to exclude from prefetching or prerendering should use the 97 * {@see 'wp_speculation_rules_href_exclude_paths'} filter to ensure those URL patterns are excluded. 98 * 99 * Additional speculation rules other than the default rule from WordPress Core can be provided by using the 100 * {@see 'wp_load_speculation_rules'} action and amending the passed WP_Speculation_Rules object. 101 * 102 * @since 6.8.0 103 * @access private 104 * 105 * @return WP_Speculation_Rules|null Object representing the speculation rules to use, or null if speculative loading 106 * is disabled in the current context. 107 */ 108 function wp_get_speculation_rules(): ?WP_Speculation_Rules { 109 $configuration = wp_get_speculation_rules_configuration(); 110 if ( null === $configuration ) { 111 return null; 112 } 113 114 $mode = $configuration['mode']; 115 $eagerness = $configuration['eagerness']; 116 117 $prefixer = new WP_URL_Pattern_Prefixer(); 118 119 $base_href_exclude_paths = array( 120 $prefixer->prefix_path_pattern( '/wp-*.php', 'site' ), 121 $prefixer->prefix_path_pattern( '/wp-admin/*', 'site' ), 122 $prefixer->prefix_path_pattern( '/*', 'uploads' ), 123 $prefixer->prefix_path_pattern( '/*', 'content' ), 124 $prefixer->prefix_path_pattern( '/*', 'plugins' ), 125 $prefixer->prefix_path_pattern( '/*', 'template' ), 126 $prefixer->prefix_path_pattern( '/*', 'stylesheet' ), 127 ); 128 129 /* 130 * If pretty permalinks are enabled, exclude any URLs with query parameters. 131 * Otherwise, exclude specifically the URLs with a `_wpnonce` query parameter or any other query parameter 132 * containing the word `nonce`. 133 */ 134 if ( get_option( 'permalink_structure' ) ) { 135 $base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*\\?(.+)', 'home' ); 136 } else { 137 $base_href_exclude_paths[] = $prefixer->prefix_path_pattern( '/*\\?*(^|&)*nonce*=*', 'home' ); 138 } 139 140 /** 141 * Filters the paths for which speculative loading should be disabled. 142 * 143 * All paths should start in a forward slash, relative to the root document. The `*` can be used as a wildcard. 144 * If the WordPress site is in a subdirectory, the exclude paths will automatically be prefixed as necessary. 145 * 146 * Note that WordPress always excludes certain path patterns such as `/wp-login.php` and `/wp-admin/*`, and those 147 * cannot be modified using the filter. 148 * 149 * @since 6.8.0 150 * 151 * @param string[] $href_exclude_paths Additional path patterns to disable speculative loading for. 152 * @param string $mode Mode used to apply speculative loading. Either 'prefetch' or 'prerender'. 153 */ 154 $href_exclude_paths = (array) apply_filters( 'wp_speculation_rules_href_exclude_paths', array(), $mode ); 155 156 // Ensure that: 157 // 1. There are no duplicates. 158 // 2. The base paths cannot be removed. 159 // 3. The array has sequential keys (i.e. array_is_list()). 160 $href_exclude_paths = array_values( 161 array_unique( 162 array_merge( 163 $base_href_exclude_paths, 164 array_map( 165 static function ( string $href_exclude_path ) use ( $prefixer ): string { 166 return $prefixer->prefix_path_pattern( $href_exclude_path ); 167 }, 168 $href_exclude_paths 169 ) 170 ) 171 ) 172 ); 173 174 $speculation_rules = new WP_Speculation_Rules(); 175 176 $main_rule_conditions = array( 177 // Include any URLs within the same site. 178 array( 179 'href_matches' => $prefixer->prefix_path_pattern( '/*' ), 180 ), 181 // Except for excluded paths. 182 array( 183 'not' => array( 184 'href_matches' => $href_exclude_paths, 185 ), 186 ), 187 // Also exclude rel=nofollow links, as certain plugins use that on their links that perform an action. 188 array( 189 'not' => array( 190 'selector_matches' => 'a[rel~="nofollow"]', 191 ), 192 ), 193 // Also exclude links that are explicitly marked to opt out. 194 array( 195 'not' => array( 196 'selector_matches' => ".no-{$mode}", 197 ), 198 ), 199 ); 200 201 // If using 'prerender', also exclude links that opt-out of 'prefetch' because it's part of 'prerender'. 202 if ( 'prerender' === $mode ) { 203 $main_rule_conditions[] = array( 204 'not' => array( 205 'selector_matches' => '.no-prefetch', 206 ), 207 ); 208 } 209 210 $speculation_rules->add_rule( 211 $mode, 212 'main', 213 array( 214 'source' => 'document', 215 'where' => array( 216 'and' => $main_rule_conditions, 217 ), 218 'eagerness' => $eagerness, 219 ) 220 ); 221 222 /** 223 * Fires when speculation rules data is loaded, allowing to amend the rules. 224 * 225 * @since 6.8.0 226 * 227 * @param WP_Speculation_Rules $speculation_rules Object representing the speculation rules to use. 228 */ 229 do_action( 'wp_load_speculation_rules', $speculation_rules ); 230 231 return $speculation_rules; 232 } 233 234 /** 235 * Prints the speculation rules. 236 * 237 * For browsers that do not support speculation rules yet, the `script[type="speculationrules"]` tag will be ignored. 238 * 239 * @since 6.8.0 240 * @access private 241 */ 242 function wp_print_speculation_rules(): void { 243 $speculation_rules = wp_get_speculation_rules(); 244 if ( null === $speculation_rules ) { 245 return; 246 } 247 248 wp_print_inline_script_tag( 249 (string) wp_json_encode( 250 $speculation_rules 251 ), 252 array( 'type' => 'speculationrules' ) 253 ); 254 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Fri Feb 21 08:20:01 2025 | Cross-referenced by PHPXref |