Changeset 56033 for trunk/src/wp-includes/class-wp-scripts.php
- Timestamp:
- 06/26/2023 01:40:31 PM (18 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-scripts.php
r55703 r56033 135 135 136 136 /** 137 * Holds a mapping of dependents (as handles) for a given script handle. 138 * Used to optimize recursive dependency tree checks. 139 * 140 * @since 6.3.0 141 * @var array 142 */ 143 private $dependents_map = array(); 144 145 /** 146 * Holds a reference to the delayed (non-blocking) script loading strategies. 147 * Used by methods that validate loading strategies. 148 * 149 * @since 6.3.0 150 * @var string[] 151 */ 152 private $delayed_strategies = array( 'defer', 'async' ); 153 154 /** 137 155 * Constructor. 138 156 * … … 285 303 } 286 304 287 $src = $obj->src; 288 $cond_before = ''; 289 $cond_after = ''; 290 $conditional = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : ''; 305 $src = $obj->src; 306 $strategy = $this->get_eligible_loading_strategy( $handle ); 307 $intended_strategy = (string) $this->get_data( $handle, 'strategy' ); 308 $cond_before = ''; 309 $cond_after = ''; 310 $conditional = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : ''; 311 312 if ( ! $this->is_delayed_strategy( $intended_strategy ) ) { 313 $intended_strategy = ''; 314 } 291 315 292 316 if ( $conditional ) { … … 295 319 } 296 320 297 $before_handle = $this->print_inline_script( $handle, 'before', false ); 298 $after_handle = $this->print_inline_script( $handle, 'after', false ); 299 300 if ( $before_handle ) { 301 $before_handle = sprintf( "<script%s id='%s-js-before'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), $before_handle ); 302 } 303 304 if ( $after_handle ) { 305 $after_handle = sprintf( "<script%s id='%s-js-after'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), $after_handle ); 306 } 307 308 if ( $before_handle || $after_handle ) { 309 $inline_script_tag = $cond_before . $before_handle . $after_handle . $cond_after; 321 $before_script = $this->get_inline_script_tag( $handle, 'before' ); 322 $after_script = $this->get_inline_script_tag( $handle, 'after' ); 323 324 if ( $before_script || $after_script ) { 325 $inline_script_tag = $cond_before . $before_script . $after_script . $cond_after; 310 326 } else { 311 327 $inline_script_tag = ''; … … 334 350 $srce = apply_filters( 'script_loader_src', $src, $handle ); 335 351 336 if ( $this->in_default_dir( $srce ) && ( $before_handle || $after_handle || $translations_stop_concat ) ) { 352 if ( 353 $this->in_default_dir( $srce ) 354 && ( $before_script || $after_script || $translations_stop_concat || $this->is_delayed_strategy( $strategy ) ) 355 ) { 337 356 $this->do_concat = false; 338 357 … … 391 410 } 392 411 393 $tag = $translations . $cond_before . $before_handle; 394 $tag .= sprintf( "<script%s src='%s' id='%s-js'></script>\n", $this->type_attr, $src, esc_attr( $handle ) ); 395 $tag .= $after_handle . $cond_after; 412 $tag = $translations . $cond_before . $before_script; 413 $tag .= sprintf( 414 "<script%s src='%s' id='%s-js'%s%s></script>\n", 415 $this->type_attr, 416 $src, // Value is escaped above. 417 esc_attr( $handle ), 418 $strategy ? " {$strategy}" : '', 419 $intended_strategy ? " data-wp-strategy='{$intended_strategy}'" : '' 420 ); 421 $tag .= $after_script . $cond_after; 396 422 397 423 /** … … 446 472 * 447 473 * @since 4.5.0 448 * 449 * @param string $handle Name of the script to add the inline script to. 474 * @deprecated 6.3.0 Use methods get_inline_script_tag() or get_inline_script_data() instead. 475 * 476 * @param string $handle Name of the script to print inline scripts for. 450 477 * Must be lowercase. 451 478 * @param string $position Optional. Whether to add the inline script 452 479 * before the handle or after. Default 'after'. 453 * @param bool $display Optional. Whether to print the script 454 * instead of just returning it. Default true.455 * @return string|false Script on success, false otherwise.480 * @param bool $display Optional. Whether to print the script tag 481 * instead of just returning the script data. Default true. 482 * @return string|false Script data on success, false otherwise. 456 483 */ 457 484 public function print_inline_script( $handle, $position = 'after', $display = true ) { 458 $output = $this->get_data( $handle, $position ); 459 485 _deprecated_function( __METHOD__, '6.3.0', 'WP_Scripts::get_inline_script_data() or WP_Scripts::get_inline_script_tag()' ); 486 487 $output = $this->get_inline_script_data( $handle, $position ); 460 488 if ( empty( $output ) ) { 461 489 return false; 462 490 } 463 491 464 $output = trim( implode( "\n", $output ), "\n" );465 466 492 if ( $display ) { 467 printf( "<script%s id='%s-js-%s'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), esc_attr( $position ), $output ); 468 } 469 493 echo $this->get_inline_script_tag( $handle, $position ); 494 } 470 495 return $output; 496 } 497 498 /** 499 * Gets data for inline scripts registered for a specific handle. 500 * 501 * @since 6.3.0 502 * 503 * @param string $handle Name of the script to get data for. 504 * Must be lowercase. 505 * @param string $position Optional. Whether to add the inline script 506 * before the handle or after. Default 'after'. 507 * @return string Inline script, which may be empty string. 508 */ 509 public function get_inline_script_data( $handle, $position = 'after' ) { 510 $data = $this->get_data( $handle, $position ); 511 if ( empty( $data ) || ! is_array( $data ) ) { 512 return ''; 513 } 514 515 return trim( implode( "\n", $data ), "\n" ); 516 } 517 518 /** 519 * Gets unaliased dependencies. 520 * 521 * An alias is a dependency whose src is false. It is used as a way to bundle multiple dependencies in a single 522 * handle. This in effect flattens an alias dependency tree. 523 * 524 * @since 6.3.0 525 * 526 * @param string[] $deps Dependency handles. 527 * @return string[] Unaliased handles. 528 */ 529 private function get_unaliased_deps( array $deps ) { 530 $flattened = array(); 531 foreach ( $deps as $dep ) { 532 if ( ! isset( $this->registered[ $dep ] ) ) { 533 continue; 534 } 535 536 if ( $this->registered[ $dep ]->src ) { 537 $flattened[] = $dep; 538 } elseif ( $this->registered[ $dep ]->deps ) { 539 array_push( $flattened, ...$this->get_unaliased_deps( $this->registered[ $dep ]->deps ) ); 540 } 541 } 542 return $flattened; 543 } 544 545 /** 546 * Gets tags for inline scripts registered for a specific handle. 547 * 548 * @since 6.3.0 549 * 550 * @param string $handle Name of the script to get associated inline script tag for. 551 * Must be lowercase. 552 * @param string $position Optional. Whether to get tag for inline 553 * scripts in the before or after position. Default 'after'. 554 * @return string Inline script, which may be empty string. 555 */ 556 public function get_inline_script_tag( $handle, $position = 'after' ) { 557 $js = $this->get_inline_script_data( $handle, $position ); 558 if ( empty( $js ) ) { 559 return ''; 560 } 561 562 $id = "{$handle}-js-{$position}"; 563 564 return wp_get_inline_script_tag( $js, compact( 'id' ) ); 471 565 } 472 566 … … 716 810 717 811 /** 812 * This overrides the add_data method from WP_Dependencies, to support normalizing of $args. 813 * 814 * @since 6.3.0 815 * 816 * @param string $handle Name of the item. Should be unique. 817 * @param string $key The data key. 818 * @param mixed $value The data value. 819 * @return bool True on success, false on failure. 820 */ 821 public function add_data( $handle, $key, $value ) { 822 if ( ! isset( $this->registered[ $handle ] ) ) { 823 return false; 824 } 825 826 if ( 'strategy' === $key ) { 827 if ( ! empty( $value ) && ! $this->is_delayed_strategy( $value ) ) { 828 _doing_it_wrong( 829 __METHOD__, 830 sprintf( 831 /* translators: 1: $strategy, 2: $handle */ 832 __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ), 833 $value, 834 $handle 835 ), 836 '6.3.0' 837 ); 838 return false; 839 } elseif ( ! $this->registered[ $handle ]->src && $this->is_delayed_strategy( $value ) ) { 840 _doing_it_wrong( 841 __METHOD__, 842 sprintf( 843 /* translators: 1: $strategy, 2: $handle */ 844 __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ), 845 $value, 846 $handle 847 ), 848 '6.3.0' 849 ); 850 return false; 851 } 852 } 853 return parent::add_data( $handle, $key, $value ); 854 } 855 856 /** 857 * Gets all dependents of a script. 858 * 859 * @since 6.3.0 860 * 861 * @param string $handle The script handle. 862 * @return string[] Script handles. 863 */ 864 private function get_dependents( $handle ) { 865 // Check if dependents map for the handle in question is present. If so, use it. 866 if ( isset( $this->dependents_map[ $handle ] ) ) { 867 return $this->dependents_map[ $handle ]; 868 } 869 870 $dependents = array(); 871 872 // Iterate over all registered scripts, finding dependents of the script passed to this method. 873 foreach ( $this->registered as $registered_handle => $args ) { 874 if ( in_array( $handle, $args->deps, true ) ) { 875 $dependents[] = $registered_handle; 876 } 877 } 878 879 // Add the handles dependents to the map to ease future lookups. 880 $this->dependents_map[ $handle ] = $dependents; 881 882 return $dependents; 883 } 884 885 /** 886 * Checks if the strategy passed is a valid delayed (non-blocking) strategy. 887 * 888 * @since 6.3.0 889 * 890 * @param string $strategy The strategy to check. 891 * @return bool True if $strategy is one of the delayed strategies, otherwise false. 892 */ 893 private function is_delayed_strategy( $strategy ) { 894 return in_array( 895 $strategy, 896 $this->delayed_strategies, 897 true 898 ); 899 } 900 901 /** 902 * Gets the best eligible loading strategy for a script. 903 * 904 * @since 6.3.0 905 * 906 * @param string $handle The script handle. 907 * @return string The best eligible loading strategy. 908 */ 909 private function get_eligible_loading_strategy( $handle ) { 910 $eligible = $this->filter_eligible_strategies( $handle ); 911 912 // Bail early once we know the eligible strategy is blocking. 913 if ( empty( $eligible ) ) { 914 return ''; 915 } 916 917 return in_array( 'async', $eligible, true ) ? 'async' : 'defer'; 918 } 919 920 /** 921 * Filter the list of eligible loading strategies for a script. 922 * 923 * @since 6.3.0 924 * 925 * @param string $handle The script handle. 926 * @param string[]|null $eligible Optional. The list of strategies to filter. Default null. 927 * @param array<string, true> $checked Optional. An array of already checked script handles, used to avoid recursive loops. 928 * @return string[] A list of eligible loading strategies that could be used. 929 */ 930 private function filter_eligible_strategies( $handle, $eligible = null, $checked = array() ) { 931 // If no strategies are being passed, all strategies are eligible. 932 if ( null === $eligible ) { 933 $eligible = $this->delayed_strategies; 934 } 935 936 // If this handle was already checked, return early. 937 if ( isset( $checked[ $handle ] ) ) { 938 return $eligible; 939 } 940 941 // Mark this handle as checked. 942 $checked[ $handle ] = true; 943 944 // If this handle isn't registered, don't filter anything and return. 945 if ( ! isset( $this->registered[ $handle ] ) ) { 946 return $eligible; 947 } 948 949 // If the handle is not enqueued, don't filter anything and return. 950 if ( ! $this->query( $handle, 'enqueued' ) ) { 951 return $eligible; 952 } 953 954 $is_alias = (bool) ! $this->registered[ $handle ]->src; 955 $intended_strategy = $this->get_data( $handle, 'strategy' ); 956 957 // For non-alias handles, an empty intended strategy filters all strategies. 958 if ( ! $is_alias && empty( $intended_strategy ) ) { 959 return array(); 960 } 961 962 // Handles with inline scripts attached in the 'after' position cannot be delayed. 963 if ( $this->has_inline_script( $handle, 'after' ) ) { 964 return array(); 965 } 966 967 // If the intended strategy is 'defer', filter out 'async'. 968 if ( 'defer' === $intended_strategy ) { 969 $eligible = array( 'defer' ); 970 } 971 972 $dependents = $this->get_dependents( $handle ); 973 974 // Recursively filter eligible strategies for dependents. 975 foreach ( $dependents as $dependent ) { 976 // Bail early once we know the eligible strategy is blocking. 977 if ( empty( $eligible ) ) { 978 return array(); 979 } 980 981 $eligible = $this->filter_eligible_strategies( $dependent, $eligible, $checked ); 982 } 983 984 return $eligible; 985 } 986 987 /** 988 * Gets data for inline scripts registered for a specific handle. 989 * 990 * @since 6.3.0 991 * 992 * @param string $handle Name of the script to get data for. Must be lowercase. 993 * @param string $position The position of the inline script. 994 * @return bool Whether the handle has an inline script (either before or after). 995 */ 996 private function has_inline_script( $handle, $position = null ) { 997 if ( $position && in_array( $position, array( 'before', 'after' ), true ) ) { 998 return (bool) $this->get_data( $handle, $position ); 999 } 1000 1001 return (bool) ( $this->get_data( $handle, 'before' ) || $this->get_data( $handle, 'after' ) ); 1002 } 1003 1004 /** 718 1005 * Resets class properties. 719 1006 *
Note: See TracChangeset
for help on using the changeset viewer.