| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Dependencies API: WP_Dependencies base class 4 * 5 * @since 2.6.0 6 * 7 * @package WordPress 8 * @subpackage Dependencies 9 */ 10 11 /** 12 * Core base class extended to register items. 13 * 14 * @since 2.6.0 15 * 16 * @see _WP_Dependency 17 */ 18 #[AllowDynamicProperties] 19 class WP_Dependencies { 20 /** 21 * An array of all registered dependencies keyed by handle. 22 * 23 * @since 2.6.8 24 * 25 * @var _WP_Dependency[] 26 */ 27 public $registered = array(); 28 29 /** 30 * An array of handles of queued dependencies. 31 * 32 * @since 2.6.8 33 * 34 * @var string[] 35 */ 36 public $queue = array(); 37 38 /** 39 * An array of handles of dependencies to queue. 40 * 41 * @since 2.6.0 42 * 43 * @var string[] 44 */ 45 public $to_do = array(); 46 47 /** 48 * An array of handles of dependencies already queued. 49 * 50 * @since 2.6.0 51 * 52 * @var string[] 53 */ 54 public $done = array(); 55 56 /** 57 * An array of additional arguments passed when a handle is registered. 58 * 59 * The keys are dependency handles and the values are query strings which are appended to the item URL's query 60 * string, after the `ver` if provided. 61 * 62 * @since 2.6.0 63 * 64 * @var array<string, string> 65 */ 66 public $args = array(); 67 68 /** 69 * An array of dependency groups to enqueue. 70 * 71 * Each entry is keyed by handle and represents the integer group level or boolean 72 * false if the handle has no group. 73 * 74 * @since 2.8.0 75 * 76 * @var (int|false)[] 77 */ 78 public $groups = array(); 79 80 /** 81 * A handle group to enqueue. 82 * 83 * @since 2.8.0 84 * 85 * @deprecated 4.5.0 86 * @var int 87 */ 88 public $group = 0; 89 90 /** 91 * Cached lookup array of flattened queued items and dependencies. 92 * 93 * @since 5.4.0 94 * 95 * @var ?array<string, true> 96 */ 97 private $all_queued_deps; 98 99 /** 100 * List of assets enqueued before details were registered. 101 * 102 * @since 5.9.0 103 * 104 * @var array<string, string|null> 105 */ 106 private $queued_before_register = array(); 107 108 /** 109 * List of handles for dependencies encountered which themselves have missing dependencies. 110 * 111 * A dependency handle is added to this list when it is discovered to have missing dependencies. At this time, a 112 * warning is emitted with {@see _doing_it_wrong()}. The handle is then added to this list, so that duplicate 113 * warnings don't occur. 114 * 115 * @since 6.9.1 116 * @var string[] 117 */ 118 private $dependencies_with_missing_dependencies = array(); 119 120 /** 121 * Processes the items and dependencies. 122 * 123 * Processes the items passed to it or the queue, and their dependencies. 124 * 125 * @since 2.6.0 126 * @since 2.8.0 Added the `$group` parameter. 127 * 128 * @param string|string[]|false $handles Optional. Items to be processed: queue (false), 129 * single item (string), or multiple items (array of strings). 130 * Default false. 131 * @param int|false $group Optional. Group level: level (int), no group (false). 132 * @return string[] Array of handles of items that have been processed. 133 */ 134 public function do_items( $handles = false, $group = false ) { 135 /* 136 * If nothing is passed, print the queue. If a string is passed, 137 * print that item. If an array is passed, print those items. 138 */ 139 $handles = false === $handles ? $this->queue : (array) $handles; 140 $this->all_deps( $handles ); 141 142 foreach ( $this->to_do as $key => $handle ) { 143 if ( ! in_array( $handle, $this->done, true ) && isset( $this->registered[ $handle ] ) ) { 144 /* 145 * Attempt to process the item. If successful, 146 * add the handle to the done array. 147 * 148 * Unset the item from the to_do array. 149 */ 150 if ( $this->do_item( $handle, $group ) ) { 151 $this->done[] = $handle; 152 } 153 154 unset( $this->to_do[ $key ] ); 155 } 156 } 157 158 return $this->done; 159 } 160 161 /** 162 * Processes a dependency. 163 * 164 * @since 2.6.0 165 * @since 5.5.0 Added the `$group` parameter. 166 * 167 * @param string $handle Name of the item. Should be unique. 168 * @param int|false $group Optional. Group level: level (int), no group (false). 169 * Default false. 170 * @return bool True on success, false if not set. 171 */ 172 public function do_item( $handle, $group = false ) { 173 return isset( $this->registered[ $handle ] ); 174 } 175 176 /** 177 * Determines dependencies. 178 * 179 * Recursively builds an array of items to process taking 180 * dependencies into account. Does NOT catch infinite loops. 181 * 182 * @since 2.1.0 183 * @since 2.6.0 Moved from `WP_Scripts`. 184 * @since 2.8.0 Added the `$group` parameter. 185 * 186 * @param string|string[] $handles Item handle (string) or item handles (array of strings). 187 * @param bool $recursion Optional. Internal flag that function is calling itself. 188 * Default false. 189 * @param int|false $group Optional. Group level: level (int), no group (false). 190 * Default false. 191 * @return bool True on success, false on failure. 192 */ 193 public function all_deps( $handles, $recursion = false, $group = false ) { 194 $handles = (array) $handles; 195 if ( ! $handles ) { 196 return false; 197 } 198 199 foreach ( $handles as $handle ) { 200 $handle_parts = explode( '?', $handle ); 201 $handle = $handle_parts[0]; 202 $queued = in_array( $handle, $this->to_do, true ); 203 204 if ( in_array( $handle, $this->done, true ) ) { // Already done. 205 continue; 206 } 207 208 $moved = $this->set_group( $handle, $recursion, $group ); 209 $new_group = $this->groups[ $handle ]; 210 211 if ( $queued && ! $moved ) { // Already queued and in the right group. 212 continue; 213 } 214 215 $keep_going = true; 216 $missing_dependencies = array(); 217 if ( isset( $this->registered[ $handle ] ) && count( $this->registered[ $handle ]->deps ) > 0 ) { 218 $missing_dependencies = array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) ); 219 } 220 if ( ! isset( $this->registered[ $handle ] ) ) { 221 $keep_going = false; // Item doesn't exist. 222 } elseif ( count( $missing_dependencies ) > 0 ) { 223 if ( ! in_array( $handle, $this->dependencies_with_missing_dependencies, true ) ) { 224 _doing_it_wrong( 225 get_class( $this ) . '::add', 226 $this->get_dependency_warning_message( $handle, $missing_dependencies ), 227 '6.9.1' 228 ); 229 $this->dependencies_with_missing_dependencies[] = $handle; 230 } 231 $keep_going = false; // Item requires dependencies that don't exist. 232 } elseif ( $this->registered[ $handle ]->deps && ! $this->all_deps( $this->registered[ $handle ]->deps, true, $new_group ) ) { 233 $keep_going = false; // Item requires dependencies that don't exist. 234 } 235 236 if ( ! $keep_going ) { // Either item or its dependencies don't exist. 237 if ( $recursion ) { 238 return false; // Abort this branch. 239 } else { 240 continue; // We're at the top level. Move on to the next one. 241 } 242 } 243 244 if ( $queued ) { // Already grabbed it and its dependencies. 245 continue; 246 } 247 248 if ( isset( $handle_parts[1] ) ) { 249 $this->args[ $handle ] = $handle_parts[1]; 250 } 251 252 $this->to_do[] = $handle; 253 } 254 255 return true; 256 } 257 258 /** 259 * Register an item. 260 * 261 * Registers the item if no item of that name already exists. 262 * 263 * @since 2.1.0 264 * @since 2.6.0 Moved from `WP_Scripts`. 265 * 266 * @param string $handle Name of the item. Should be unique. 267 * @param string|false $src Full URL of the item, or path of the item relative 268 * to the WordPress root directory. If source is set to false, 269 * the item is an alias of other items it depends on. 270 * @param string[] $deps Optional. An array of registered item handles this item depends on. 271 * Default empty array. 272 * @param string|bool|null $ver Optional. String specifying item version number, if it has one, 273 * which is added to the URL as a query string for cache busting purposes. 274 * If version is set to false, a version number is automatically added 275 * equal to current installed WordPress version. 276 * If set to null, no version is added. 277 * @param mixed $args Optional. Custom property of the item. NOT the class property $args. 278 * Examples: $media, $in_footer. 279 * @return bool Whether the item has been registered. True on success, false on failure. 280 */ 281 public function add( $handle, $src, $deps = array(), $ver = false, $args = null ) { 282 if ( isset( $this->registered[ $handle ] ) ) { 283 return false; 284 } 285 $this->registered[ $handle ] = new _WP_Dependency( $handle, $src, $deps, $ver, $args ); 286 287 // If the item was enqueued before the details were registered, enqueue it now. 288 if ( array_key_exists( $handle, $this->queued_before_register ) ) { 289 if ( ! is_null( $this->queued_before_register[ $handle ] ) ) { 290 $this->enqueue( $handle . '?' . $this->queued_before_register[ $handle ] ); 291 } else { 292 $this->enqueue( $handle ); 293 } 294 295 unset( $this->queued_before_register[ $handle ] ); 296 } 297 298 return true; 299 } 300 301 /** 302 * Add extra item data. 303 * 304 * Adds data to a registered item. 305 * 306 * @since 2.6.0 307 * 308 * @param string $handle Name of the item. Should be unique. 309 * @param string $key The data key. 310 * @param mixed $value The data value. 311 * @return bool True on success, false on failure. 312 */ 313 public function add_data( $handle, $key, $value ) { 314 if ( ! isset( $this->registered[ $handle ] ) ) { 315 return false; 316 } 317 if ( 'conditional' === $key && '_required-conditional-dependency_' !== $value ) { 318 _deprecated_argument( 319 'WP_Dependencies->add_data()', 320 '6.9.0', 321 __( 'IE conditional comments are ignored by all supported browsers.' ) 322 ); 323 } 324 325 return $this->registered[ $handle ]->add_data( $key, $value ); 326 } 327 328 /** 329 * Get extra item data. 330 * 331 * Gets data associated with a registered item. 332 * 333 * @since 3.3.0 334 * 335 * @param string $handle Name of the item. Should be unique. 336 * @param string $key The data key. 337 * @return mixed Extra item data (string), false otherwise. 338 */ 339 public function get_data( $handle, $key ) { 340 if ( ! isset( $this->registered[ $handle ] ) ) { 341 return false; 342 } 343 344 if ( ! isset( $this->registered[ $handle ]->extra[ $key ] ) ) { 345 return false; 346 } 347 348 return $this->registered[ $handle ]->extra[ $key ]; 349 } 350 351 /** 352 * Un-register an item or items. 353 * 354 * @since 2.1.0 355 * @since 2.6.0 Moved from `WP_Scripts`. 356 * 357 * @param string|string[] $handles Item handle (string) or item handles (array of strings). 358 */ 359 public function remove( $handles ) { 360 foreach ( (array) $handles as $handle ) { 361 unset( $this->registered[ $handle ] ); 362 } 363 } 364 365 /** 366 * Queue an item or items. 367 * 368 * Decodes handles and arguments, then queues handles and stores 369 * arguments in the class property $args. For example in extending 370 * classes, $args is appended to the item url as a query string. 371 * Note $args is NOT the $args property of items in the $registered array. 372 * 373 * @since 2.1.0 374 * @since 2.6.0 Moved from `WP_Scripts`. 375 * 376 * @param string|string[] $handles Item handle (string) or item handles (array of strings). 377 */ 378 public function enqueue( $handles ) { 379 foreach ( (array) $handles as $handle ) { 380 $handle = explode( '?', $handle ); 381 382 if ( ! in_array( $handle[0], $this->queue, true ) && isset( $this->registered[ $handle[0] ] ) ) { 383 $this->queue[] = $handle[0]; 384 385 // Reset all dependencies so they must be recalculated in recurse_deps(). 386 $this->all_queued_deps = null; 387 388 if ( isset( $handle[1] ) ) { 389 $this->args[ $handle[0] ] = $handle[1]; 390 } 391 } elseif ( ! isset( $this->registered[ $handle[0] ] ) ) { 392 $this->queued_before_register[ $handle[0] ] = null; // $args 393 394 if ( isset( $handle[1] ) ) { 395 $this->queued_before_register[ $handle[0] ] = $handle[1]; 396 } 397 } 398 } 399 } 400 401 /** 402 * Dequeue an item or items. 403 * 404 * Decodes handles and arguments, then dequeues handles 405 * and removes arguments from the class property $args. 406 * 407 * @since 2.1.0 408 * @since 2.6.0 Moved from `WP_Scripts`. 409 * 410 * @param string|string[] $handles Item handle (string) or item handles (array of strings). 411 */ 412 public function dequeue( $handles ) { 413 foreach ( (array) $handles as $handle ) { 414 $handle = explode( '?', $handle ); 415 $key = array_search( $handle[0], $this->queue, true ); 416 417 if ( false !== $key ) { 418 // Reset all dependencies so they must be recalculated in recurse_deps(). 419 $this->all_queued_deps = null; 420 421 unset( $this->queue[ $key ] ); 422 unset( $this->args[ $handle[0] ] ); 423 } elseif ( array_key_exists( $handle[0], $this->queued_before_register ) ) { 424 unset( $this->queued_before_register[ $handle[0] ] ); 425 } 426 } 427 } 428 429 /** 430 * Recursively search the passed dependency tree for a handle. 431 * 432 * @since 4.0.0 433 * 434 * @param string[] $queue An array of queued _WP_Dependency handles. 435 * @param string $handle Name of the item. Should be unique. 436 * @return bool Whether the handle is found after recursively searching the dependency tree. 437 */ 438 protected function recurse_deps( $queue, $handle ) { 439 if ( isset( $this->all_queued_deps ) ) { 440 return isset( $this->all_queued_deps[ $handle ] ); 441 } 442 443 $all_deps = array_fill_keys( $queue, true ); 444 $queues = array(); 445 $done = array(); 446 447 while ( $queue ) { 448 foreach ( $queue as $queued ) { 449 if ( ! isset( $done[ $queued ] ) && isset( $this->registered[ $queued ] ) ) { 450 $deps = $this->registered[ $queued ]->deps; 451 if ( $deps ) { 452 $all_deps += array_fill_keys( $deps, true ); 453 array_push( $queues, $deps ); 454 } 455 $done[ $queued ] = true; 456 } 457 } 458 $queue = array_pop( $queues ); 459 } 460 461 $this->all_queued_deps = $all_deps; 462 463 return isset( $this->all_queued_deps[ $handle ] ); 464 } 465 466 /** 467 * Query the list for an item. 468 * 469 * @since 2.1.0 470 * @since 2.6.0 Moved from `WP_Scripts`. 471 * 472 * @param string $handle Name of the item. Should be unique. 473 * @param string $status Optional. Status of the item to query. Default 'registered'. 474 * @return bool|_WP_Dependency Found, or object Item data. 475 */ 476 public function query( $handle, $status = 'registered' ) { 477 switch ( $status ) { 478 case 'registered': 479 case 'scripts': // Back compat. 480 return $this->registered[ $handle ] ?? false; 481 482 case 'enqueued': 483 case 'queue': // Back compat. 484 if ( in_array( $handle, $this->queue, true ) ) { 485 return true; 486 } 487 return $this->recurse_deps( $this->queue, $handle ); 488 489 case 'to_do': 490 case 'to_print': // Back compat. 491 return in_array( $handle, $this->to_do, true ); 492 493 case 'done': 494 case 'printed': // Back compat. 495 return in_array( $handle, $this->done, true ); 496 } 497 498 return false; 499 } 500 501 /** 502 * Set item group, unless already in a lower group. 503 * 504 * @since 2.8.0 505 * 506 * @param string $handle Name of the item. Should be unique. 507 * @param bool $recursion Internal flag that calling function was called recursively. 508 * @param int|false $group Group level: level (int), no group (false). 509 * @return bool Not already in the group or a lower group. 510 */ 511 public function set_group( $handle, $recursion, $group ) { 512 $group = (int) $group; 513 514 if ( isset( $this->groups[ $handle ] ) && $this->groups[ $handle ] <= $group ) { 515 return false; 516 } 517 518 $this->groups[ $handle ] = $group; 519 520 return true; 521 } 522 523 /** 524 * Get etag header for cache validation. 525 * 526 * @since 6.7.0 527 * 528 * @global string $wp_version The WordPress version string. 529 * 530 * @param string[] $load Array of script or style handles to load. 531 * @return string Etag header. 532 */ 533 public function get_etag( $load ) { 534 /* 535 * Note: wp_get_wp_version() is not used here, as this file can be included 536 * via wp-admin/load-scripts.php or wp-admin/load-styles.php, in which case 537 * wp-includes/functions.php is not loaded. 538 */ 539 global $wp_version; 540 541 $etag = "WP:{$wp_version};"; 542 543 foreach ( $load as $handle ) { 544 if ( ! array_key_exists( $handle, $this->registered ) ) { 545 continue; 546 } 547 548 $ver = $this->registered[ $handle ]->ver ?? $wp_version; 549 $etag .= "{$handle}:{$ver};"; 550 } 551 552 /* 553 * This is not intended to be cryptographically secure, just a fast way to get 554 * a fixed length string based on the script versions. As this file does not 555 * load the full WordPress environment, it is not possible to use the salted 556 * wp_hash() function. 557 */ 558 return 'W/"' . md5( $etag ) . '"'; 559 } 560 561 /** 562 * Gets a dependency warning message for a handle. 563 * 564 * @since 6.9.1 565 * 566 * @param string $handle Handle with missing dependencies. 567 * @param string[] $missing_dependency_handles Missing dependency handles. 568 * @return string Formatted, localized warning message. 569 */ 570 protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) { 571 return sprintf( 572 /* translators: 1: Handle, 2: Comma-separated list of missing dependency handles. */ 573 __( 'The handle "%1$s" was enqueued with dependencies that are not registered: %2$s.' ), 574 $handle, 575 implode( ', ', $missing_dependency_handles ) 576 ); 577 } 578 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Wed Apr 15 08:20:10 2026 | Cross-referenced by PHPXref |