[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-scripts.php (source)

   1  <?php
   2  /**
   3   * Dependencies API: WP_Scripts class
   4   *
   5   * @since 2.6.0
   6   *
   7   * @package WordPress
   8   * @subpackage Dependencies
   9   */
  10  
  11  /**
  12   * Core class used to register scripts.
  13   *
  14   * @since 2.1.0
  15   *
  16   * @see WP_Dependencies
  17   */
  18  class WP_Scripts extends WP_Dependencies {
  19      /**
  20       * Base URL for scripts.
  21       *
  22       * Full URL with trailing slash.
  23       *
  24       * @since 2.6.0
  25       * @var string
  26       */
  27      public $base_url;
  28  
  29      /**
  30       * URL of the content directory.
  31       *
  32       * @since 2.8.0
  33       * @var string
  34       */
  35      public $content_url;
  36  
  37      /**
  38       * Default version string for scripts.
  39       *
  40       * @since 2.6.0
  41       * @var string
  42       */
  43      public $default_version;
  44  
  45      /**
  46       * Holds handles of scripts which are enqueued in footer.
  47       *
  48       * @since 2.8.0
  49       * @var array
  50       */
  51      public $in_footer = array();
  52  
  53      /**
  54       * Holds a list of script handles which will be concatenated.
  55       *
  56       * @since 2.8.0
  57       * @var string
  58       */
  59      public $concat = '';
  60  
  61      /**
  62       * Holds a string which contains script handles and their version.
  63       *
  64       * @since 2.8.0
  65       * @deprecated 3.4.0
  66       * @var string
  67       */
  68      public $concat_version = '';
  69  
  70      /**
  71       * Whether to perform concatenation.
  72       *
  73       * @since 2.8.0
  74       * @var bool
  75       */
  76      public $do_concat = false;
  77  
  78      /**
  79       * Holds HTML markup of scripts and additional data if concatenation
  80       * is enabled.
  81       *
  82       * @since 2.8.0
  83       * @var string
  84       */
  85      public $print_html = '';
  86  
  87      /**
  88       * Holds inline code if concatenation is enabled.
  89       *
  90       * @since 2.8.0
  91       * @var string
  92       */
  93      public $print_code = '';
  94  
  95      /**
  96       * Holds a list of script handles which are not in the default directory
  97       * if concatenation is enabled.
  98       *
  99       * Unused in core.
 100       *
 101       * @since 2.8.0
 102       * @var string
 103       */
 104      public $ext_handles = '';
 105  
 106      /**
 107       * Holds a string which contains handles and versions of scripts which
 108       * are not in the default directory if concatenation is enabled.
 109       *
 110       * Unused in core.
 111       *
 112       * @since 2.8.0
 113       * @var string
 114       */
 115      public $ext_version = '';
 116  
 117      /**
 118       * List of default directories.
 119       *
 120       * @since 2.8.0
 121       * @var array
 122       */
 123      public $default_dirs;
 124  
 125      /**
 126       * Holds a mapping of dependents (as handles) for a given script handle.
 127       * Used to optimize recursive dependency tree checks.
 128       *
 129       * @since 6.3.0
 130       * @var array
 131       */
 132      private $dependents_map = array();
 133  
 134      /**
 135       * Holds a reference to the delayed (non-blocking) script loading strategies.
 136       * Used by methods that validate loading strategies.
 137       *
 138       * @since 6.3.0
 139       * @var string[]
 140       */
 141      private $delayed_strategies = array( 'defer', 'async' );
 142  
 143      /**
 144       * Constructor.
 145       *
 146       * @since 2.6.0
 147       */
 148  	public function __construct() {
 149          $this->init();
 150          add_action( 'init', array( $this, 'init' ), 0 );
 151      }
 152  
 153      /**
 154       * Initialize the class.
 155       *
 156       * @since 3.4.0
 157       */
 158  	public function init() {
 159          /**
 160           * Fires when the WP_Scripts instance is initialized.
 161           *
 162           * @since 2.6.0
 163           *
 164           * @param WP_Scripts $wp_scripts WP_Scripts instance (passed by reference).
 165           */
 166          do_action_ref_array( 'wp_default_scripts', array( &$this ) );
 167      }
 168  
 169      /**
 170       * Prints scripts.
 171       *
 172       * Prints the scripts passed to it or the print queue. Also prints all necessary dependencies.
 173       *
 174       * @since 2.1.0
 175       * @since 2.8.0 Added the `$group` parameter.
 176       *
 177       * @param string|string[]|false $handles Optional. Scripts to be printed: queue (false),
 178       *                                       single script (string), or multiple scripts (array of strings).
 179       *                                       Default false.
 180       * @param int|false             $group   Optional. Group level: level (int), no groups (false).
 181       *                                       Default false.
 182       * @return string[] Handles of scripts that have been printed.
 183       */
 184  	public function print_scripts( $handles = false, $group = false ) {
 185          return $this->do_items( $handles, $group );
 186      }
 187  
 188      /**
 189       * Prints extra scripts of a registered script.
 190       *
 191       * @since 2.1.0
 192       * @since 2.8.0 Added the `$display` parameter.
 193       * @deprecated 3.3.0
 194       *
 195       * @see print_extra_script()
 196       *
 197       * @param string $handle  The script's registered handle.
 198       * @param bool   $display Optional. Whether to print the extra script
 199       *                        instead of just returning it. Default true.
 200       * @return bool|string|void Void if no data exists, extra scripts if `$display` is true,
 201       *                          true otherwise.
 202       */
 203  	public function print_scripts_l10n( $handle, $display = true ) {
 204          _deprecated_function( __FUNCTION__, '3.3.0', 'WP_Scripts::print_extra_script()' );
 205          return $this->print_extra_script( $handle, $display );
 206      }
 207  
 208      /**
 209       * Prints extra scripts of a registered script.
 210       *
 211       * @since 3.3.0
 212       *
 213       * @param string $handle  The script's registered handle.
 214       * @param bool   $display Optional. Whether to print the extra script
 215       *                        instead of just returning it. Default true.
 216       * @return bool|string|void Void if no data exists, extra scripts if `$display` is true,
 217       *                          true otherwise.
 218       */
 219  	public function print_extra_script( $handle, $display = true ) {
 220          $output = $this->get_data( $handle, 'data' );
 221          if ( ! $output ) {
 222              return;
 223          }
 224  
 225          /*
 226           * Do not print a sourceURL comment if concatenation is enabled.
 227           *
 228           * Extra scripts may be concatenated into a single script.
 229           * The line-based sourceURL comments may break concatenated scripts
 230           * and do not make sense when multiple scripts are joined together.
 231           */
 232          if ( ! $this->do_concat ) {
 233              $output .= sprintf(
 234                  "\n//# sourceURL=%s",
 235                  rawurlencode( "{$handle}-js-extra" )
 236              );
 237          }
 238  
 239          if ( ! $display ) {
 240              return $output;
 241          }
 242  
 243          wp_print_inline_script_tag( $output, array( 'id' => "{$handle}-js-extra" ) );
 244  
 245          return true;
 246      }
 247  
 248      /**
 249       * Checks whether all dependents of a given handle are in the footer.
 250       *
 251       * If there are no dependents, this is considered the same as if all dependents were in the footer.
 252       *
 253       * @since 6.4.0
 254       *
 255       * @param string $handle Script handle.
 256       * @return bool Whether all dependents are in the footer.
 257       */
 258  	private function are_all_dependents_in_footer( $handle ) {
 259          foreach ( $this->get_dependents( $handle ) as $dep ) {
 260              if ( isset( $this->groups[ $dep ] ) && 0 === $this->groups[ $dep ] ) {
 261                  return false;
 262              }
 263          }
 264          return true;
 265      }
 266  
 267      /**
 268       * Processes a script dependency.
 269       *
 270       * @since 2.6.0
 271       * @since 2.8.0 Added the `$group` parameter.
 272       *
 273       * @see WP_Dependencies::do_item()
 274       *
 275       * @param string    $handle The script's registered handle.
 276       * @param int|false $group  Optional. Group level: level (int), no groups (false).
 277       *                          Default false.
 278       * @return bool True on success, false on failure.
 279       */
 280  	public function do_item( $handle, $group = false ) {
 281          if ( ! parent::do_item( $handle ) ) {
 282              return false;
 283          }
 284  
 285          if ( 0 === $group && $this->groups[ $handle ] > 0 ) {
 286              $this->in_footer[] = $handle;
 287              return false;
 288          }
 289  
 290          if ( false === $group && in_array( $handle, $this->in_footer, true ) ) {
 291              $this->in_footer = array_diff( $this->in_footer, (array) $handle );
 292          }
 293  
 294          $obj = $this->registered[ $handle ];
 295  
 296          if ( null === $obj->ver ) {
 297              $ver = '';
 298          } else {
 299              $ver = $obj->ver ? $obj->ver : $this->default_version;
 300          }
 301  
 302          if ( isset( $this->args[ $handle ] ) ) {
 303              $ver = $ver ? $ver . '&amp;' . $this->args[ $handle ] : $this->args[ $handle ];
 304          }
 305  
 306          $src                   = $obj->src;
 307          $strategy              = $this->get_eligible_loading_strategy( $handle );
 308          $intended_strategy     = (string) $this->get_data( $handle, 'strategy' );
 309          $ie_conditional_prefix = '';
 310          $ie_conditional_suffix = '';
 311          $conditional           = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : '';
 312  
 313          if ( ! $this->is_delayed_strategy( $intended_strategy ) ) {
 314              $intended_strategy = '';
 315          }
 316  
 317          /*
 318           * Move this script to the footer if:
 319           * 1. The script is in the header group.
 320           * 2. The current output is the header.
 321           * 3. The intended strategy is delayed.
 322           * 4. The actual strategy is not delayed.
 323           * 5. All dependent scripts are in the footer.
 324           */
 325          if (
 326              0 === $group &&
 327              0 === $this->groups[ $handle ] &&
 328              $intended_strategy &&
 329              ! $this->is_delayed_strategy( $strategy ) &&
 330              $this->are_all_dependents_in_footer( $handle )
 331          ) {
 332              $this->in_footer[] = $handle;
 333              return false;
 334          }
 335  
 336          if ( $conditional ) {
 337              $ie_conditional_prefix = "<!--[if {$conditional}]>\n";
 338              $ie_conditional_suffix = "<![endif]-->\n";
 339          }
 340  
 341          $before_script = $this->get_inline_script_tag( $handle, 'before' );
 342          $after_script  = $this->get_inline_script_tag( $handle, 'after' );
 343  
 344          if ( $before_script || $after_script ) {
 345              $inline_script_tag = $ie_conditional_prefix . $before_script . $after_script . $ie_conditional_suffix;
 346          } else {
 347              $inline_script_tag = '';
 348          }
 349  
 350          /*
 351           * Prevent concatenation of scripts if the text domain is defined
 352           * to ensure the dependency order is respected.
 353           */
 354          $translations_stop_concat = ! empty( $obj->textdomain );
 355  
 356          $translations = $this->print_translations( $handle, false );
 357          if ( $translations ) {
 358              $translations = wp_get_inline_script_tag( $translations, array( 'id' => "{$handle}-js-translations" ) );
 359          }
 360  
 361          if ( $this->do_concat ) {
 362              /**
 363               * Filters the script loader source.
 364               *
 365               * @since 2.2.0
 366               *
 367               * @param string $src    Script loader source path.
 368               * @param string $handle Script handle.
 369               */
 370              $filtered_src = apply_filters( 'script_loader_src', $src, $handle );
 371  
 372              if (
 373                  $this->in_default_dir( $filtered_src )
 374                  && ( $before_script || $after_script || $translations_stop_concat || $this->is_delayed_strategy( $strategy ) )
 375              ) {
 376                  $this->do_concat = false;
 377  
 378                  // Have to print the so-far concatenated scripts right away to maintain the right order.
 379                  _print_scripts();
 380                  $this->reset();
 381              } elseif ( $this->in_default_dir( $filtered_src ) && ! $conditional ) {
 382                  $this->print_code     .= $this->print_extra_script( $handle, false );
 383                  $this->concat         .= "$handle,";
 384                  $this->concat_version .= "$handle$ver";
 385                  return true;
 386              } else {
 387                  $this->ext_handles .= "$handle,";
 388                  $this->ext_version .= "$handle$ver";
 389              }
 390          }
 391  
 392          $has_conditional_data = $conditional && $this->get_data( $handle, 'data' );
 393  
 394          if ( $has_conditional_data ) {
 395              echo $ie_conditional_prefix;
 396          }
 397  
 398          $this->print_extra_script( $handle );
 399  
 400          if ( $has_conditional_data ) {
 401              echo $ie_conditional_suffix;
 402          }
 403  
 404          // A single item may alias a set of items, by having dependencies, but no source.
 405          if ( ! $src ) {
 406              if ( $inline_script_tag ) {
 407                  if ( $this->do_concat ) {
 408                      $this->print_html .= $inline_script_tag;
 409                  } else {
 410                      echo $inline_script_tag;
 411                  }
 412              }
 413  
 414              return true;
 415          }
 416  
 417          if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $this->content_url && str_starts_with( $src, $this->content_url ) ) ) {
 418              $src = $this->base_url . $src;
 419          }
 420  
 421          if ( ! empty( $ver ) ) {
 422              $src = add_query_arg( 'ver', $ver, $src );
 423          }
 424  
 425          /** This filter is documented in wp-includes/class-wp-scripts.php */
 426          $src = esc_url_raw( apply_filters( 'script_loader_src', $src, $handle ) );
 427  
 428          if ( ! $src ) {
 429              return true;
 430          }
 431  
 432          $attr = array(
 433              'src' => $src,
 434              'id'  => "{$handle}-js",
 435          );
 436          if ( $strategy ) {
 437              $attr[ $strategy ] = true;
 438          }
 439          if ( $intended_strategy ) {
 440              $attr['data-wp-strategy'] = $intended_strategy;
 441          }
 442          if ( isset( $obj->extra['fetchpriority'] ) && 'auto' !== $obj->extra['fetchpriority'] && $this->is_valid_fetchpriority( $obj->extra['fetchpriority'] ) ) {
 443              $attr['fetchpriority'] = $obj->extra['fetchpriority'];
 444          }
 445          $tag  = $translations . $ie_conditional_prefix . $before_script;
 446          $tag .= wp_get_script_tag( $attr );
 447          $tag .= $after_script . $ie_conditional_suffix;
 448  
 449          /**
 450           * Filters the HTML script tag of an enqueued script.
 451           *
 452           * @since 4.1.0
 453           *
 454           * @param string $tag    The `<script>` tag for the enqueued script.
 455           * @param string $handle The script's registered handle.
 456           * @param string $src    The script's source URL.
 457           */
 458          $tag = apply_filters( 'script_loader_tag', $tag, $handle, $src );
 459  
 460          if ( $this->do_concat ) {
 461              $this->print_html .= $tag;
 462          } else {
 463              echo $tag;
 464          }
 465  
 466          return true;
 467      }
 468  
 469      /**
 470       * Adds extra code to a registered script.
 471       *
 472       * @since 4.5.0
 473       *
 474       * @param string $handle   Name of the script to add the inline script to.
 475       *                         Must be lowercase.
 476       * @param string $data     String containing the JavaScript to be added.
 477       * @param string $position Optional. Whether to add the inline script
 478       *                         before the handle or after. Default 'after'.
 479       * @return bool True on success, false on failure.
 480       */
 481  	public function add_inline_script( $handle, $data, $position = 'after' ) {
 482          if ( ! $data ) {
 483              return false;
 484          }
 485  
 486          if ( 'after' !== $position ) {
 487              $position = 'before';
 488          }
 489  
 490          $script   = (array) $this->get_data( $handle, $position );
 491          $script[] = $data;
 492  
 493          return $this->add_data( $handle, $position, $script );
 494      }
 495  
 496      /**
 497       * Prints inline scripts registered for a specific handle.
 498       *
 499       * @since 4.5.0
 500       * @deprecated 6.3.0 Use methods get_inline_script_tag() or get_inline_script_data() instead.
 501       *
 502       * @param string $handle   Name of the script to print inline scripts for.
 503       *                         Must be lowercase.
 504       * @param string $position Optional. Whether to add the inline script
 505       *                         before the handle or after. Default 'after'.
 506       * @param bool   $display  Optional. Whether to print the script tag
 507       *                         instead of just returning the script data. Default true.
 508       * @return string|false Script data on success, false otherwise.
 509       */
 510  	public function print_inline_script( $handle, $position = 'after', $display = true ) {
 511          _deprecated_function( __METHOD__, '6.3.0', 'WP_Scripts::get_inline_script_data() or WP_Scripts::get_inline_script_tag()' );
 512  
 513          $output = $this->get_inline_script_data( $handle, $position );
 514          if ( empty( $output ) ) {
 515              return false;
 516          }
 517  
 518          if ( $display ) {
 519              echo $this->get_inline_script_tag( $handle, $position );
 520          }
 521          return $output;
 522      }
 523  
 524      /**
 525       * Gets data for inline scripts registered for a specific handle.
 526       *
 527       * @since 6.3.0
 528       *
 529       * @param string $handle   Name of the script to get data for.
 530       *                         Must be lowercase.
 531       * @param string $position Optional. Whether to add the inline script
 532       *                         before the handle or after. Default 'after'.
 533       * @return string Inline script, which may be empty string.
 534       */
 535  	public function get_inline_script_data( $handle, $position = 'after' ) {
 536          $data = $this->get_data( $handle, $position );
 537          if ( empty( $data ) || ! is_array( $data ) ) {
 538              return '';
 539          }
 540  
 541          /*
 542           * Print sourceURL comment regardless of concatenation.
 543           *
 544           * Inline scripts prevent scripts from being concatenated, so
 545           * sourceURL comments are safe to print for inline scripts.
 546           */
 547          $data[] = sprintf(
 548              '//# sourceURL=%s',
 549              rawurlencode( "{$handle}-js-{$position}" )
 550          );
 551  
 552          return trim( implode( "\n", $data ), "\n" );
 553      }
 554  
 555      /**
 556       * Gets tags for inline scripts registered for a specific handle.
 557       *
 558       * @since 6.3.0
 559       *
 560       * @param string $handle   Name of the script to get associated inline script tag for.
 561       *                         Must be lowercase.
 562       * @param string $position Optional. Whether to get tag for inline
 563       *                         scripts in the before or after position. Default 'after'.
 564       * @return string Inline script, which may be empty string.
 565       */
 566  	public function get_inline_script_tag( $handle, $position = 'after' ) {
 567          $js = $this->get_inline_script_data( $handle, $position );
 568          if ( empty( $js ) ) {
 569              return '';
 570          }
 571  
 572          $id = "{$handle}-js-{$position}";
 573  
 574          return wp_get_inline_script_tag( $js, compact( 'id' ) );
 575      }
 576  
 577      /**
 578       * Localizes a script, only if the script has already been added.
 579       *
 580       * @since 2.1.0
 581       *
 582       * @param string $handle      Name of the script to attach data to.
 583       * @param string $object_name Name of the variable that will contain the data.
 584       * @param array  $l10n        Array of data to localize.
 585       * @return bool True on success, false on failure.
 586       */
 587  	public function localize( $handle, $object_name, $l10n ) {
 588          if ( 'jquery' === $handle ) {
 589              $handle = 'jquery-core';
 590          }
 591  
 592          if ( is_array( $l10n ) && isset( $l10n['l10n_print_after'] ) ) { // back compat, preserve the code in 'l10n_print_after' if present.
 593              $after = $l10n['l10n_print_after'];
 594              unset( $l10n['l10n_print_after'] );
 595          }
 596  
 597          if ( ! is_array( $l10n ) ) {
 598              _doing_it_wrong(
 599                  __METHOD__,
 600                  sprintf(
 601                      /* translators: 1: $l10n, 2: wp_add_inline_script() */
 602                      __( 'The %1$s parameter must be an array. To pass arbitrary data to scripts, use the %2$s function instead.' ),
 603                      '<code>$l10n</code>',
 604                      '<code>wp_add_inline_script()</code>'
 605                  ),
 606                  '5.7.0'
 607              );
 608  
 609              if ( false === $l10n ) {
 610                  // This should really not be needed, but is necessary for backward compatibility.
 611                  $l10n = array( $l10n );
 612              }
 613          }
 614  
 615          if ( is_string( $l10n ) ) {
 616              $l10n = html_entity_decode( $l10n, ENT_QUOTES, 'UTF-8' );
 617          } elseif ( is_array( $l10n ) ) {
 618              foreach ( $l10n as $key => $value ) {
 619                  if ( ! is_scalar( $value ) ) {
 620                      continue;
 621                  }
 622  
 623                  $l10n[ $key ] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' );
 624              }
 625          }
 626  
 627          $script = "var $object_name = " . wp_json_encode( $l10n, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ';';
 628  
 629          if ( ! empty( $after ) ) {
 630              $script .= "\n$after;";
 631          }
 632  
 633          $data = $this->get_data( $handle, 'data' );
 634  
 635          if ( ! empty( $data ) ) {
 636              $script = "$data\n$script";
 637          }
 638  
 639          return $this->add_data( $handle, 'data', $script );
 640      }
 641  
 642      /**
 643       * Sets handle group.
 644       *
 645       * @since 2.8.0
 646       *
 647       * @see WP_Dependencies::set_group()
 648       *
 649       * @param string    $handle    Name of the item. Should be unique.
 650       * @param bool      $recursion Internal flag that calling function was called recursively.
 651       * @param int|false $group     Optional. Group level: level (int), no groups (false).
 652       *                             Default false.
 653       * @return bool Not already in the group or a lower group.
 654       */
 655  	public function set_group( $handle, $recursion, $group = false ) {
 656          if ( isset( $this->registered[ $handle ]->args ) && 1 === $this->registered[ $handle ]->args ) {
 657              $calculated_group = 1;
 658          } else {
 659              $calculated_group = (int) $this->get_data( $handle, 'group' );
 660          }
 661  
 662          if ( false !== $group && $calculated_group > $group ) {
 663              $calculated_group = $group;
 664          }
 665  
 666          return parent::set_group( $handle, $recursion, $calculated_group );
 667      }
 668  
 669      /**
 670       * Sets a translation textdomain.
 671       *
 672       * @since 5.0.0
 673       * @since 5.1.0 The `$domain` parameter was made optional.
 674       *
 675       * @param string $handle Name of the script to register a translation domain to.
 676       * @param string $domain Optional. Text domain. Default 'default'.
 677       * @param string $path   Optional. The full file path to the directory containing translation files.
 678       * @return bool True if the text domain was registered, false if not.
 679       */
 680  	public function set_translations( $handle, $domain = 'default', $path = '' ) {
 681          if ( ! isset( $this->registered[ $handle ] ) ) {
 682              return false;
 683          }
 684  
 685          /** @var \_WP_Dependency $obj */
 686          $obj = $this->registered[ $handle ];
 687  
 688          if ( ! in_array( 'wp-i18n', $obj->deps, true ) ) {
 689              $obj->deps[] = 'wp-i18n';
 690          }
 691  
 692          return $obj->set_translations( $domain, $path );
 693      }
 694  
 695      /**
 696       * Prints translations set for a specific handle.
 697       *
 698       * @since 5.0.0
 699       *
 700       * @param string $handle  Name of the script to add the inline script to.
 701       *                        Must be lowercase.
 702       * @param bool   $display Optional. Whether to print the script
 703       *                        instead of just returning it. Default true.
 704       * @return string|false Script on success, false otherwise.
 705       */
 706  	public function print_translations( $handle, $display = true ) {
 707          if ( ! isset( $this->registered[ $handle ] ) || empty( $this->registered[ $handle ]->textdomain ) ) {
 708              return false;
 709          }
 710  
 711          $domain = $this->registered[ $handle ]->textdomain;
 712          $path   = '';
 713  
 714          if ( isset( $this->registered[ $handle ]->translations_path ) ) {
 715              $path = $this->registered[ $handle ]->translations_path;
 716          }
 717  
 718          $json_translations = load_script_textdomain( $handle, $domain, $path );
 719  
 720          if ( ! $json_translations ) {
 721              return false;
 722          }
 723  
 724          $source_url = rawurlencode( "{$handle}-js-translations" );
 725  
 726          $output = <<<JS
 727  ( function( domain, translations ) {
 728      var localeData = translations.locale_data[ domain ] || translations.locale_data.messages;
 729      localeData[""].domain = domain;
 730      wp.i18n.setLocaleData( localeData, domain );
 731  } )( "{$domain}", {$json_translations} );
 732  //# sourceURL={$source_url}
 733  JS;
 734  
 735          if ( $display ) {
 736              wp_print_inline_script_tag( $output, array( 'id' => "{$handle}-js-translations" ) );
 737          }
 738  
 739          return $output;
 740      }
 741  
 742      /**
 743       * Determines script dependencies.
 744       *
 745       * @since 2.1.0
 746       *
 747       * @see WP_Dependencies::all_deps()
 748       *
 749       * @param string|string[] $handles   Item handle (string) or item handles (array of strings).
 750       * @param bool            $recursion Optional. Internal flag that function is calling itself.
 751       *                                   Default false.
 752       * @param int|false       $group     Optional. Group level: level (int), no groups (false).
 753       *                                   Default false.
 754       * @return bool True on success, false on failure.
 755       */
 756  	public function all_deps( $handles, $recursion = false, $group = false ) {
 757          $result = parent::all_deps( $handles, $recursion, $group );
 758          if ( ! $recursion ) {
 759              /**
 760               * Filters the list of script dependencies left to print.
 761               *
 762               * @since 2.3.0
 763               *
 764               * @param string[] $to_do An array of script dependency handles.
 765               */
 766              $this->to_do = apply_filters( 'print_scripts_array', $this->to_do );
 767          }
 768          return $result;
 769      }
 770  
 771      /**
 772       * Processes items and dependencies for the head group.
 773       *
 774       * @since 2.8.0
 775       *
 776       * @see WP_Dependencies::do_items()
 777       *
 778       * @return string[] Handles of items that have been processed.
 779       */
 780  	public function do_head_items() {
 781          $this->do_items( false, 0 );
 782          return $this->done;
 783      }
 784  
 785      /**
 786       * Processes items and dependencies for the footer group.
 787       *
 788       * @since 2.8.0
 789       *
 790       * @see WP_Dependencies::do_items()
 791       *
 792       * @return string[] Handles of items that have been processed.
 793       */
 794  	public function do_footer_items() {
 795          $this->do_items( false, 1 );
 796          return $this->done;
 797      }
 798  
 799      /**
 800       * Whether a handle's source is in a default directory.
 801       *
 802       * @since 2.8.0
 803       *
 804       * @param string $src The source of the enqueued script.
 805       * @return bool True if found, false if not.
 806       */
 807  	public function in_default_dir( $src ) {
 808          if ( ! $this->default_dirs ) {
 809              return true;
 810          }
 811  
 812          if ( str_starts_with( $src, '/' . WPINC . '/js/l10n' ) ) {
 813              return false;
 814          }
 815  
 816          foreach ( (array) $this->default_dirs as $test ) {
 817              if ( str_starts_with( $src, $test ) ) {
 818                  return true;
 819              }
 820          }
 821          return false;
 822      }
 823  
 824      /**
 825       * This overrides the add_data method from WP_Dependencies, to support normalizing of $args.
 826       *
 827       * @since 6.3.0
 828       *
 829       * @param string $handle Name of the item. Should be unique.
 830       * @param string $key    The data key.
 831       * @param mixed  $value  The data value.
 832       * @return bool True on success, false on failure.
 833       */
 834  	public function add_data( $handle, $key, $value ) {
 835          if ( ! isset( $this->registered[ $handle ] ) ) {
 836              return false;
 837          }
 838  
 839          if ( 'strategy' === $key ) {
 840              if ( ! empty( $value ) && ! $this->is_delayed_strategy( $value ) ) {
 841                  _doing_it_wrong(
 842                      __METHOD__,
 843                      sprintf(
 844                          /* translators: 1: $strategy, 2: $handle */
 845                          __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ),
 846                          $value,
 847                          $handle
 848                      ),
 849                      '6.3.0'
 850                  );
 851                  return false;
 852              } elseif ( ! $this->registered[ $handle ]->src && $this->is_delayed_strategy( $value ) ) {
 853                  _doing_it_wrong(
 854                      __METHOD__,
 855                      sprintf(
 856                          /* translators: 1: $strategy, 2: $handle */
 857                          __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ),
 858                          $value,
 859                          $handle
 860                      ),
 861                      '6.3.0'
 862                  );
 863                  return false;
 864              }
 865          } elseif ( 'fetchpriority' === $key ) {
 866              if ( empty( $value ) ) {
 867                  $value = 'auto';
 868              }
 869              if ( ! $this->is_valid_fetchpriority( $value ) ) {
 870                  _doing_it_wrong(
 871                      __METHOD__,
 872                      sprintf(
 873                          /* translators: 1: $fetchpriority, 2: $handle */
 874                          __( 'Invalid fetchpriority `%1$s` defined for `%2$s` during script registration.' ),
 875                          is_string( $value ) ? $value : gettype( $value ),
 876                          $handle
 877                      ),
 878                      '6.9.0'
 879                  );
 880                  return false;
 881              } elseif ( ! $this->registered[ $handle ]->src ) {
 882                  _doing_it_wrong(
 883                      __METHOD__,
 884                      sprintf(
 885                          /* translators: 1: $fetchpriority, 2: $handle */
 886                          __( 'Cannot supply a fetchpriority `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ),
 887                          is_string( $value ) ? $value : gettype( $value ),
 888                          $handle
 889                      ),
 890                      '6.9.0'
 891                  );
 892                  return false;
 893              }
 894          }
 895          return parent::add_data( $handle, $key, $value );
 896      }
 897  
 898      /**
 899       * Gets all dependents of a script.
 900       *
 901       * @since 6.3.0
 902       *
 903       * @param string $handle The script handle.
 904       * @return string[] Script handles.
 905       */
 906  	private function get_dependents( $handle ) {
 907          // Check if dependents map for the handle in question is present. If so, use it.
 908          if ( isset( $this->dependents_map[ $handle ] ) ) {
 909              return $this->dependents_map[ $handle ];
 910          }
 911  
 912          $dependents = array();
 913  
 914          // Iterate over all registered scripts, finding dependents of the script passed to this method.
 915          foreach ( $this->registered as $registered_handle => $args ) {
 916              if ( in_array( $handle, $args->deps, true ) ) {
 917                  $dependents[] = $registered_handle;
 918              }
 919          }
 920  
 921          // Add the handles dependents to the map to ease future lookups.
 922          $this->dependents_map[ $handle ] = $dependents;
 923  
 924          return $dependents;
 925      }
 926  
 927      /**
 928       * Checks if the strategy passed is a valid delayed (non-blocking) strategy.
 929       *
 930       * @since 6.3.0
 931       *
 932       * @param string|mixed $strategy The strategy to check.
 933       * @return bool True if $strategy is one of the delayed strategies, otherwise false.
 934       */
 935  	private function is_delayed_strategy( $strategy ): bool {
 936          return in_array(
 937              $strategy,
 938              $this->delayed_strategies,
 939              true
 940          );
 941      }
 942  
 943      /**
 944       * Checks if the provided fetchpriority is valid.
 945       *
 946       * @since 6.9.0
 947       *
 948       * @param string|mixed $priority Fetch priority.
 949       * @return bool Whether valid fetchpriority.
 950       */
 951  	private function is_valid_fetchpriority( $priority ): bool {
 952          return in_array( $priority, array( 'auto', 'low', 'high' ), true );
 953      }
 954  
 955      /**
 956       * Gets the best eligible loading strategy for a script.
 957       *
 958       * @since 6.3.0
 959       *
 960       * @param string $handle The script handle.
 961       * @return string The best eligible loading strategy.
 962       */
 963  	private function get_eligible_loading_strategy( $handle ) {
 964          $intended_strategy = (string) $this->get_data( $handle, 'strategy' );
 965  
 966          // Bail early if there is no intended strategy.
 967          if ( ! $intended_strategy ) {
 968              return '';
 969          }
 970  
 971          /*
 972           * If the intended strategy is 'defer', limit the initial list of eligible
 973           * strategies, since 'async' can fallback to 'defer', but not vice-versa.
 974           */
 975          $initial_strategy = ( 'defer' === $intended_strategy ) ? array( 'defer' ) : null;
 976  
 977          $eligible_strategies = $this->filter_eligible_strategies( $handle, $initial_strategy );
 978  
 979          // Return early once we know the eligible strategy is blocking.
 980          if ( empty( $eligible_strategies ) ) {
 981              return '';
 982          }
 983  
 984          return in_array( 'async', $eligible_strategies, true ) ? 'async' : 'defer';
 985      }
 986  
 987      /**
 988       * Filter the list of eligible loading strategies for a script.
 989       *
 990       * @since 6.3.0
 991       *
 992       * @param string              $handle              The script handle.
 993       * @param string[]|null       $eligible_strategies Optional. The list of strategies to filter. Default null.
 994       * @param array<string, true> $checked             Optional. An array of already checked script handles, used to avoid recursive loops.
 995       * @return string[] A list of eligible loading strategies that could be used.
 996       */
 997  	private function filter_eligible_strategies( $handle, $eligible_strategies = null, $checked = array() ) {
 998          // If no strategies are being passed, all strategies are eligible.
 999          if ( null === $eligible_strategies ) {
1000              $eligible_strategies = $this->delayed_strategies;
1001          }
1002  
1003          // If this handle was already checked, return early.
1004          if ( isset( $checked[ $handle ] ) ) {
1005              return $eligible_strategies;
1006          }
1007  
1008          // Mark this handle as checked.
1009          $checked[ $handle ] = true;
1010  
1011          // If this handle isn't registered, don't filter anything and return.
1012          if ( ! isset( $this->registered[ $handle ] ) ) {
1013              return $eligible_strategies;
1014          }
1015  
1016          // If the handle is not enqueued, don't filter anything and return.
1017          if ( ! $this->query( $handle, 'enqueued' ) ) {
1018              return $eligible_strategies;
1019          }
1020  
1021          $is_alias          = (bool) ! $this->registered[ $handle ]->src;
1022          $intended_strategy = $this->get_data( $handle, 'strategy' );
1023  
1024          // For non-alias handles, an empty intended strategy filters all strategies.
1025          if ( ! $is_alias && empty( $intended_strategy ) ) {
1026              return array();
1027          }
1028  
1029          // Handles with inline scripts attached in the 'after' position cannot be delayed.
1030          if ( $this->has_inline_script( $handle, 'after' ) ) {
1031              return array();
1032          }
1033  
1034          // If the intended strategy is 'defer', filter out 'async'.
1035          if ( 'defer' === $intended_strategy ) {
1036              $eligible_strategies = array( 'defer' );
1037          }
1038  
1039          $dependents = $this->get_dependents( $handle );
1040  
1041          // Recursively filter eligible strategies for dependents.
1042          foreach ( $dependents as $dependent ) {
1043              // Bail early once we know the eligible strategy is blocking.
1044              if ( empty( $eligible_strategies ) ) {
1045                  return array();
1046              }
1047  
1048              $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked );
1049          }
1050  
1051          return $eligible_strategies;
1052      }
1053  
1054      /**
1055       * Gets data for inline scripts registered for a specific handle.
1056       *
1057       * @since 6.3.0
1058       *
1059       * @param string $handle   Name of the script to get data for. Must be lowercase.
1060       * @param string $position The position of the inline script.
1061       * @return bool Whether the handle has an inline script (either before or after).
1062       */
1063  	private function has_inline_script( $handle, $position = null ) {
1064          if ( $position && in_array( $position, array( 'before', 'after' ), true ) ) {
1065              return (bool) $this->get_data( $handle, $position );
1066          }
1067  
1068          return (bool) ( $this->get_data( $handle, 'before' ) || $this->get_data( $handle, 'after' ) );
1069      }
1070  
1071      /**
1072       * Resets class properties.
1073       *
1074       * @since 2.8.0
1075       */
1076  	public function reset() {
1077          $this->do_concat      = false;
1078          $this->print_code     = '';
1079          $this->concat         = '';
1080          $this->concat_version = '';
1081          $this->print_html     = '';
1082          $this->ext_version    = '';
1083          $this->ext_handles    = '';
1084      }
1085  }


Generated : Wed Sep 17 08:20:04 2025 Cross-referenced by PHPXref