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