| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Dependencies API: WP_Styles class 4 * 5 * @since 2.6.0 6 * 7 * @package WordPress 8 * @subpackage Dependencies 9 */ 10 11 /** 12 * Core class used to register styles. 13 * 14 * @since 2.6.0 15 * 16 * @see WP_Dependencies 17 */ 18 class WP_Styles extends WP_Dependencies { 19 /** 20 * Base URL for styles. 21 * 22 * Full URL with trailing slash. 23 * 24 * @since 2.6.0 25 * @see wp_default_styles() 26 * @var string|null 27 */ 28 public $base_url; 29 30 /** 31 * URL of the content directory. 32 * 33 * @since 2.8.0 34 * @see wp_default_styles() 35 * @var string|null 36 */ 37 public $content_url; 38 39 /** 40 * Default version string for stylesheets. 41 * 42 * @since 2.6.0 43 * @see wp_default_styles() 44 * @var string|null 45 */ 46 public $default_version; 47 48 /** 49 * The current text direction. 50 * 51 * @since 2.6.0 52 * @see wp_default_styles() 53 * @var string 54 */ 55 public $text_direction = 'ltr'; 56 57 /** 58 * Holds a list of style handles which will be concatenated. 59 * 60 * @since 2.8.0 61 * @deprecated 7.2.0 Styles are no longer concatenated. 62 * @var string 63 */ 64 public $concat = ''; 65 66 /** 67 * Holds a string which contains style handles and their version. 68 * 69 * @since 2.8.0 70 * @deprecated 3.4.0 71 * @var string 72 */ 73 public $concat_version = ''; 74 75 /** 76 * Whether to perform concatenation. 77 * 78 * @since 2.8.0 79 * @deprecated 7.2.0 Styles are no longer concatenated. 80 * @var bool 81 */ 82 public $do_concat = false; 83 84 /** 85 * Holds HTML markup of styles and additional data if concatenation 86 * is enabled. 87 * 88 * @since 2.8.0 89 * @deprecated 7.2.0 Styles are no longer concatenated. 90 * @var string 91 */ 92 public $print_html = ''; 93 94 /** 95 * Holds inline styles if concatenation is enabled. 96 * 97 * @since 3.3.0 98 * @deprecated 7.2.0 Styles are no longer concatenated. 99 * @var string 100 */ 101 public $print_code = ''; 102 103 /** 104 * List of default directories. 105 * 106 * Only the deprecated {@see WP_Styles::in_default_dir()} reads this, but 107 * {@see wp_default_styles()} still sets it for plugins that read it. 108 * 109 * @since 2.8.0 110 * @deprecated 7.2.0 Styles are no longer concatenated. 111 * @see WP_Styles::in_default_dir() 112 * @see wp_default_styles() 113 * @var string[]|null 114 */ 115 public $default_dirs; 116 117 /** 118 * Constructor. 119 * 120 * @since 2.6.0 121 */ 122 public function __construct() { 123 /** 124 * Fires when the WP_Styles instance is initialized. 125 * 126 * @since 2.6.0 127 * 128 * @param WP_Styles $wp_styles WP_Styles instance (passed by reference). 129 */ 130 do_action_ref_array( 'wp_default_styles', array( &$this ) ); 131 } 132 133 /** 134 * Processes a style dependency. 135 * 136 * @since 2.6.0 137 * @since 5.5.0 Added the `$group` parameter. 138 * 139 * @see WP_Dependencies::do_item() 140 * 141 * @param string $handle The style's registered handle. 142 * @param int|false $group Optional. Group level: level (int), no groups (false). 143 * Default false. 144 * @return bool True on success, false on failure. 145 */ 146 public function do_item( $handle, $group = false ) { 147 if ( ! parent::do_item( $handle ) ) { 148 return false; 149 } 150 151 $obj = $this->registered[ $handle ]; 152 if ( $obj->extra['conditional'] ?? false ) { 153 154 return false; 155 } 156 157 $src = $obj->src; 158 $inline_style = $this->print_inline_style( $handle, false ); 159 160 if ( $inline_style ) { 161 $processor = new WP_HTML_Tag_Processor( '<style></style>' ); 162 $processor->next_tag(); 163 $processor->set_attribute( 'id', "{$handle}-inline-css" ); 164 $processor->set_modifiable_text( "\n{$inline_style}\n" ); 165 $inline_style_tag = "{$processor->get_updated_html()}\n"; 166 } else { 167 $inline_style_tag = ''; 168 } 169 170 $media = $obj->args ?? 'all'; 171 172 // A single item may alias a set of items, by having dependencies, but no source. 173 if ( ! $src ) { 174 if ( $inline_style_tag ) { 175 echo $inline_style_tag; 176 } 177 178 return true; 179 } 180 181 $href = $this->_css_href( $src, $obj->ver, $handle ); 182 if ( ! $href ) { 183 return true; 184 } 185 186 $rel = isset( $obj->extra['alt'] ) && $obj->extra['alt'] ? 'alternate stylesheet' : 'stylesheet'; 187 $title = $obj->extra['title'] ?? ''; 188 189 $tag = sprintf( 190 "<link rel='%s' id='%s-css'%s href='%s' media='%s' />\n", 191 $rel, 192 esc_attr( $handle ), 193 $title ? sprintf( " title='%s'", esc_attr( $title ) ) : '', 194 $href, 195 esc_attr( $media ) 196 ); 197 198 /** 199 * Filters the HTML link tag of an enqueued style. 200 * 201 * @since 2.6.0 202 * @since 4.3.0 Introduced the `$href` parameter. 203 * @since 4.5.0 Introduced the `$media` parameter. 204 * 205 * @param string $tag The link tag for the enqueued style. 206 * @param string $handle The style's registered handle. 207 * @param string $href The stylesheet's source URL. 208 * @param string $media The stylesheet's media attribute. 209 */ 210 $tag = apply_filters( 'style_loader_tag', $tag, $handle, $href, $media ); 211 212 $rtl_src = $this->get_rtl_src( $handle ); 213 214 if ( null !== $rtl_src ) { 215 $rtl_href = esc_url( $rtl_src ); 216 $rtl_tag = sprintf( 217 "<link rel='%s' id='%s-rtl-css'%s href='%s' media='%s' />\n", 218 $rel, 219 esc_attr( $handle ), 220 $title ? sprintf( " title='%s'", esc_attr( $title ) ) : '', 221 $rtl_href, 222 esc_attr( $media ) 223 ); 224 225 /** This filter is documented in wp-includes/class-wp-styles.php */ 226 $rtl_tag = apply_filters( 'style_loader_tag', $rtl_tag, $handle, $rtl_href, $media ); 227 228 if ( 'replace' === $obj->extra['rtl'] ) { 229 $tag = $rtl_tag; 230 } else { 231 $tag .= $rtl_tag; 232 } 233 } 234 235 echo $tag; 236 echo $inline_style_tag; 237 238 return true; 239 } 240 241 /** 242 * Gets the URL of the right-to-left stylesheet for a registered style. 243 * 244 * On a right-to-left locale, a style registered with `rtl` data is served by a separate 245 * stylesheet, which either replaces its left-to-right one (when the data is `'replace'`) 246 * or loads alongside it. 247 * 248 * Like {@see WP_Styles::get_src()}, the URL is neither sanitized nor escaped, so a caller can 249 * pass it through esc_url() to print it, or esc_url_raw() otherwise, once. 250 * 251 * @since 7.2.0 252 * 253 * @param string $handle The style's registered handle. 254 * @return string|null URL of the right-to-left stylesheet, after the {@see 'style_loader_src'} 255 * filter. Null when the text direction is not right-to-left, or the style is 256 * not registered, has no source of its own, or has no right-to-left variant. 257 */ 258 public function get_rtl_src( string $handle ): ?string { 259 if ( 'rtl' !== $this->text_direction || ! isset( $this->registered[ $handle ] ) ) { 260 return null; 261 } 262 263 $obj = $this->registered[ $handle ]; 264 265 if ( ! $obj->src || ! isset( $obj->extra['rtl'] ) || ! $obj->extra['rtl'] ) { 266 return null; 267 } 268 269 /* 270 * The version and the handle's added arguments are those of the left-to-right stylesheet, 271 * appended the same way, while the filter is passed the handle with `-rtl` appended, as it 272 * always has been. 273 */ 274 if ( is_bool( $obj->extra['rtl'] ) || 'replace' === $obj->extra['rtl'] ) { 275 $suffix = isset( $obj->extra['suffix'] ) && is_string( $obj->extra['suffix'] ) ? $obj->extra['suffix'] : ''; 276 277 return str_replace( "{$suffix}.css", "-rtl{$suffix}.css", $this->build_src( $obj->src, $obj->ver, $handle, "$handle-rtl" ) ); 278 } 279 280 // Any other value is the URL of the right-to-left stylesheet itself. 281 if ( ! is_string( $obj->extra['rtl'] ) ) { 282 return null; 283 } 284 285 return $this->build_src( $obj->extra['rtl'], $obj->ver, $handle, "$handle-rtl" ); 286 } 287 288 /** 289 * Adds extra CSS styles to a registered stylesheet. 290 * 291 * @since 3.3.0 292 * 293 * @param string $handle The style's registered handle. 294 * @param string $code String containing the CSS styles to be added. 295 * @return bool True on success, false on failure. 296 */ 297 public function add_inline_style( $handle, $code ) { 298 if ( ! $code ) { 299 return false; 300 } 301 302 $after = $this->get_data( $handle, 'after' ); 303 if ( ! $after ) { 304 $after = array(); 305 } 306 307 $after[] = $code; 308 309 return $this->add_data( $handle, 'after', $after ); 310 } 311 312 /** 313 * Prints extra CSS styles of a registered stylesheet. 314 * 315 * @since 3.3.0 316 * 317 * @param string $handle The style's registered handle. 318 * @param bool $display Optional. Whether to print the inline style 319 * instead of just returning it. Default true. 320 * @return string|bool False if no data exists, inline styles if `$display` is false, 321 * true otherwise. 322 * @phpstan-return ( $display is true ? bool : string|false ) 323 */ 324 public function print_inline_style( $handle, $display = true ) { 325 $output = $this->get_data( $handle, 'after' ); 326 327 if ( empty( $output ) || ! is_array( $output ) ) { 328 return false; 329 } 330 331 // Obtain the original `src` for a stylesheet possibly inlined by wp_maybe_inline_styles(). 332 $inlined_src = $this->get_data( $handle, 'inlined_src' ); 333 334 // If there's only one `after` inline style, and that inline style had been inlined, then use the $inlined_src 335 // as the sourceURL. Otherwise, if there is more than one inline `after` style associated with the handle, 336 // then resort to using the handle to construct the sourceURL since there isn't a single source. 337 if ( count( $output ) === 1 && is_string( $inlined_src ) && strlen( $inlined_src ) > 0 ) { 338 $source_url = esc_url_raw( $inlined_src ); 339 } else { 340 $source_url = rawurlencode( "{$handle}-inline-css" ); 341 } 342 343 $output[] = sprintf( 344 '/*# sourceURL=%s */', 345 $source_url 346 ); 347 348 $output = implode( "\n", $output ); 349 350 if ( ! $display ) { 351 return $output; 352 } 353 354 $processor = new WP_HTML_Tag_Processor( '<style></style>' ); 355 $processor->next_tag(); 356 $processor->set_attribute( 'id', "{$handle}-inline-css" ); 357 $processor->set_modifiable_text( "\n{$output}\n" ); 358 echo "{$processor->get_updated_html()}\n"; 359 360 return true; 361 } 362 363 /** 364 * Overrides the add_data method from WP_Dependencies, to allow unsetting dependencies for conditional styles. 365 * 366 * @since 6.9.0 367 * 368 * @param string $handle Name of the item. Should be unique. 369 * @param string $key The data key. 370 * @param mixed $value The data value. 371 * @return bool True on success, false on failure. 372 */ 373 public function add_data( $handle, $key, $value ) { 374 if ( ! isset( $this->registered[ $handle ] ) ) { 375 return false; 376 } 377 378 if ( 'conditional' === $key ) { 379 $this->registered[ $handle ]->deps = array(); 380 } 381 382 return parent::add_data( $handle, $key, $value ); 383 } 384 385 /** 386 * Determines style dependencies. 387 * 388 * @since 2.6.0 389 * 390 * @see WP_Dependencies::all_deps() 391 * 392 * @param string|string[] $handles Item handle (string) or item handles (array of strings). 393 * @param bool $recursion Optional. Internal flag that function is calling itself. 394 * Default false. 395 * @param int|false $group Optional. Group level: level (int), no groups (false). 396 * Default false. 397 * @return bool True on success, false on failure. 398 */ 399 public function all_deps( $handles, $recursion = false, $group = false ) { 400 $result = parent::all_deps( $handles, $recursion, $group ); 401 if ( ! $recursion ) { 402 /** 403 * Filters the array of enqueued styles before processing for output. 404 * 405 * @since 2.6.0 406 * 407 * @param string[] $to_do The list of enqueued style handles about to be processed. 408 */ 409 $this->to_do = apply_filters( 'print_styles_array', $this->to_do ); 410 } 411 return $result; 412 } 413 414 /** 415 * Generates an enqueued style's fully-qualified URL. 416 * 417 * @since 2.6.0 418 * 419 * @param string $src The source of the enqueued style. 420 * @param string|false|null $ver The version of the enqueued style. 421 * @param string $handle The style's registered handle. 422 * @return string Style's fully-qualified URL, escaped for use in an HTML attribute. 423 */ 424 public function _css_href( $src, $ver, $handle ) { 425 return esc_url( $this->build_src( $src, $ver, (string) $handle ) ); 426 } 427 428 /** 429 * Gets the URL a registered style is loaded from. 430 * 431 * This is the URL printed in the stylesheet's `href` attribute, including the version query 432 * argument and any arguments added to the handle, after the {@see 'style_loader_src'} filter. 433 * Unlike {@see WP_Styles::_css_href()}, it is neither sanitized nor escaped, so a caller can 434 * pass it through esc_url() to print it, or esc_url_raw() otherwise, once. This is the same as 435 * {@see WP_Script_Modules::get_src()}. 436 * 437 * @since 7.2.0 438 * 439 * @param string $handle The style's registered handle. 440 * @return string Style URL, or an empty string when the style is not registered, has no 441 * source of its own because it only aliases other styles, or was filtered away. 442 */ 443 public function get_src( string $handle ): string { 444 if ( ! isset( $this->registered[ $handle ] ) ) { 445 return ''; 446 } 447 448 $obj = $this->registered[ $handle ]; 449 450 /* 451 * An alias, with no source of its own, has no URL. A source of `true`, like that of `colors`, 452 * gets past this, since its URL comes from the 'style_loader_src' filter in build_src(), as 453 * it does when WP_Styles::do_item() prints the stylesheet. 454 */ 455 if ( ! $obj->src ) { 456 return ''; 457 } 458 459 return $this->build_src( $obj->src, $obj->ver, $handle ); 460 } 461 462 /** 463 * Builds a style's fully-qualified URL and passes it through the 'style_loader_src' filter. 464 * 465 * The result is not escaped, so callers can escape it for where it is used. 466 * 467 * @since 7.2.0 468 * 469 * @param string|true $src The source of the style, or true for one whose URL comes 470 * from the {@see 'style_loader_src'} filter. 471 * @param string|false|null $ver The version of the style. 472 * @param string $handle The style's registered handle, whose added arguments 473 * are appended. 474 * @param string|null $filter_handle Optional. The handle passed to the 475 * {@see 'style_loader_src'} filter, such as 476 * `{$handle}-rtl` for a right-to-left stylesheet. 477 * Default `$handle`. 478 * @return string The filtered URL, or an empty string when the filter returns anything other 479 * than a string. 480 */ 481 private function build_src( $src, $ver, string $handle, ?string $filter_handle = null ): string { 482 if ( ! is_bool( $src ) && ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->content_url && str_starts_with( $src, $this->content_url ) ) ) { 483 $src = $this->base_url . $src; 484 } 485 486 $ver_to_add = ''; 487 if ( empty( $ver ) && null !== $ver && is_string( $this->default_version ) ) { 488 $ver_to_add = $this->default_version; 489 } elseif ( is_scalar( $ver ) ) { 490 $ver_to_add = (string) $ver; 491 } 492 493 $added_args = (string) ( $this->args[ $handle ] ?? '' ); 494 495 if ( '' !== $ver_to_add || '' !== $added_args ) { 496 $fragment = strstr( $src, '#' ); 497 if ( false !== $fragment ) { 498 $src = substr( $src, 0, -strlen( $fragment ) ); 499 } 500 501 if ( '' !== $ver_to_add ) { 502 $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . 'ver=' . rawurlencode( $ver_to_add ); 503 } 504 if ( '' !== $added_args ) { 505 $src .= ( str_contains( $src, '?' ) ? '&' : '?' ) . $added_args; 506 } 507 508 if ( false !== $fragment ) { 509 $src .= $fragment; 510 } 511 } 512 513 /** 514 * Filters an enqueued style's fully-qualified URL. 515 * 516 * @since 2.6.0 517 * 518 * @param string $src The source URL of the enqueued style. 519 * @param string $handle The style's registered handle. 520 */ 521 $src = apply_filters( 'style_loader_src', $src, $filter_handle ?? $handle ); 522 523 return is_string( $src ) ? $src : ''; 524 } 525 526 /** 527 * Whether a handle's source is in a default directory. 528 * 529 * @since 2.8.0 530 * @deprecated 7.2.0 Styles are no longer concatenated. 531 * 532 * @param string $src The source of the enqueued style. 533 * @return bool True if found, false if not. 534 */ 535 public function in_default_dir( $src ) { 536 _deprecated_function( __METHOD__, '7.2.0' ); 537 538 if ( ! $this->default_dirs ) { 539 return true; 540 } 541 542 return array_any( (array) $this->default_dirs, fn( $test ) => str_starts_with( $src, $test ) ); 543 } 544 545 /** 546 * Processes items and dependencies for the footer group. 547 * 548 * HTML 5 allows styles in the body, grab late enqueued items and output them in the footer. 549 * 550 * @since 3.3.0 551 * 552 * @see WP_Dependencies::do_items() 553 * 554 * @return string[] Handles of items that have been processed. 555 */ 556 public function do_footer_items() { 557 $this->do_items( false, 1 ); 558 return $this->done; 559 } 560 561 /** 562 * Resets class properties. 563 * 564 * @since 3.3.0 565 */ 566 public function reset() { 567 $this->do_concat = false; 568 $this->concat = ''; 569 $this->concat_version = ''; 570 $this->print_html = ''; 571 } 572 573 /** 574 * Gets a style-specific dependency warning message. 575 * 576 * @since 6.9.1 577 * 578 * @param string $handle Style handle with missing dependencies. 579 * @param string[] $missing_dependency_handles Missing dependency handles. 580 * @return string Formatted, localized warning message. 581 */ 582 protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) { 583 return sprintf( 584 /* translators: 1: Style handle, 2: List of missing dependency handles. */ 585 __( 'The style with the handle "%1$s" was enqueued with dependencies that are not registered: %2$s.' ), 586 $handle, 587 implode( wp_get_list_item_separator(), $missing_dependency_handles ) 588 ); 589 } 590 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Tue Nov 3 08:20:36 2026 | Cross-referenced by PHPXref |