| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * WordPress implementation for PHP functions either missing from older PHP versions or not included by default. 4 * 5 * This file is loaded extremely early and the functions can be relied upon by drop-ins. 6 * Ergo, please ensure you do not rely on external functions when writing code for this file. 7 * Only use functions built into PHP or are defined in this file and have adequate testing 8 * and error suppression to ensure the file will run correctly and not break websites. 9 * 10 * @package PHP 11 * @access private 12 */ 13 14 // If gettext isn't available. 15 if ( ! function_exists( '_' ) ) { 16 /** 17 * Compat function to mimic _(), an alias of gettext(). 18 * 19 * @since 0.71 20 * 21 * @see https://php.net/manual/en/function.gettext.php 22 * 23 * @param string $message The message being translated. 24 * @return string 25 */ 26 function _( $message ) { 27 return $message; 28 } 29 } 30 31 /** 32 * Returns whether PCRE/u (PCRE_UTF8 modifier) is available for use. 33 * 34 * @ignore 35 * @since 4.2.2 36 * @since 6.9.0 Deprecated the `$set` argument. 37 * @access private 38 * 39 * @param bool $set Deprecated. This argument is no longer used for testing purposes. 40 */ 41 function _wp_can_use_pcre_u( $set = null ) { 42 static $utf8_pcre = null; 43 44 if ( isset( $set ) ) { 45 _deprecated_argument( __FUNCTION__, '6.9.0' ); 46 } 47 48 if ( isset( $utf8_pcre ) ) { 49 return $utf8_pcre; 50 } 51 52 $utf8_pcre = true; 53 set_error_handler( 54 function ( $errno, $errstr ) use ( &$utf8_pcre ) { 55 if ( str_starts_with( $errstr, 'preg_match():' ) ) { 56 $utf8_pcre = false; 57 return true; 58 } 59 60 return false; 61 }, 62 E_WARNING 63 ); 64 65 /* 66 * Attempt to compile a PCRE pattern with the PCRE_UTF8 flag. For 67 * systems lacking Unicode support this will trigger a warning 68 * during compilation, which the error handler will intercept. 69 */ 70 preg_match( '//u', '' ); 71 restore_error_handler(); 72 73 return $utf8_pcre; 74 } 75 76 /** 77 * Indicates if a given slug for a character set represents the UTF-8 text encoding. 78 * 79 * A charset is considered to represent UTF-8 if it is a case-insensitive match 80 * of "UTF-8" with or without the hyphen. 81 * 82 * Example: 83 * 84 * true === _is_utf8_charset( 'UTF-8' ); 85 * true === _is_utf8_charset( 'utf8' ); 86 * false === _is_utf8_charset( 'latin1' ); 87 * false === _is_utf8_charset( 'UTF 8' ); 88 * 89 * // Only strings match. 90 * false === _is_utf8_charset( [ 'charset' => 'utf-8' ] ); 91 * 92 * `is_utf8_charset` should be used outside of this file. 93 * 94 * @ignore 95 * @since 6.6.1 96 * 97 * @param string $charset_slug Slug representing a text character encoding, or "charset". 98 * E.g. "UTF-8", "Windows-1252", "ISO-8859-1", "SJIS". 99 * 100 * @return bool Whether the slug represents the UTF-8 encoding. 101 */ 102 function _is_utf8_charset( $charset_slug ) { 103 if ( ! is_string( $charset_slug ) ) { 104 return false; 105 } 106 107 return ( 108 0 === strcasecmp( 'UTF-8', $charset_slug ) || 109 0 === strcasecmp( 'UTF8', $charset_slug ) 110 ); 111 } 112 113 if ( ! function_exists( 'mb_chr' ) ) : 114 /** 115 * Compat function to mimic mb_chr(). 116 * 117 * @ignore 118 * @since 7.1.0 119 * 120 * @see _mb_ord() 121 * 122 * @param int $codepoint A Unicode codepoint value, e.g. 128024 for U+1F418 ELEPHANT 123 * @param "UTF-8"|null $encoding Must be 'UTF-8' or null. 124 * @return string|false A string containing the requested character, if it can be represented in the specified encoding or false on failure. 125 */ 126 function mb_chr( $codepoint, $encoding = null ) { 127 return _mb_chr( $codepoint, $encoding ); 128 } 129 endif; 130 131 /** 132 * Internal compat function to mimic mb_chr(). 133 * 134 * @ignore 135 * @since 7.1.0 136 * 137 * @param int $codepoint A Unicode codepoint value, e.g. 128024 for U+1F418 ELEPHANT 138 * @param "UTF-8"|null $encoding Must be 'UTF-8' or null. 139 * @return string|false A string containing the requested character, if it can be represented in the specified encoding or false on failure. 140 */ 141 function _mb_chr( $codepoint, $encoding = null ) { 142 if ( ! is_int( $codepoint ) || ( isset( $encoding ) && 'UTF-8' !== $encoding ) ) { 143 return false; 144 } 145 146 // Pre-check to ensure a valid code point. 147 if ( 148 $codepoint < 0 || 149 ( $codepoint >= 0xD800 && $codepoint <= 0xDFFF ) || 150 $codepoint > 0x10FFFF 151 ) { 152 return false; 153 } 154 155 if ( $codepoint <= 0x7F ) { 156 return chr( $codepoint ); 157 } 158 159 if ( $codepoint <= 0x7FF ) { 160 $byte1 = chr( ( $codepoint >> 6 ) | 0xC0 ); 161 $byte2 = chr( $codepoint & 0x3F | 0x80 ); 162 163 return "{$byte1}{$byte2}"; 164 } 165 166 if ( $codepoint <= 0xFFFF ) { 167 $byte1 = chr( ( $codepoint >> 12 ) | 0xE0 ); 168 $byte2 = chr( ( $codepoint >> 6 ) & 0x3F | 0x80 ); 169 $byte3 = chr( $codepoint & 0x3F | 0x80 ); 170 171 return "{$byte1}{$byte2}{$byte3}"; 172 } 173 174 // Any values above U+10FFFF are eliminated above in the pre-check. 175 $byte1 = chr( ( $codepoint >> 18 ) | 0xF0 ); 176 $byte2 = chr( ( $codepoint >> 12 ) & 0x3F | 0x80 ); 177 $byte3 = chr( ( $codepoint >> 6 ) & 0x3F | 0x80 ); 178 $byte4 = chr( $codepoint & 0x3F | 0x80 ); 179 180 return "{$byte1}{$byte2}{$byte3}{$byte4}"; 181 } 182 183 if ( ! function_exists( 'mb_ord' ) ) : 184 /** 185 * Compat function to mimic mb_ord(). 186 * 187 * @ignore 188 * @since 7.1.0 189 * 190 * @see _mb_ord() 191 * 192 * @param string $string Return the code point at the start of this string. 193 * @param "UTF-8"|null $encoding Must be 'UTF-8' or null. 194 * @return int|false The Unicode code point for the first character of string or false on failure. 195 */ 196 function mb_ord( $string, $encoding = null ) { 197 return _mb_ord( $string, $encoding ); 198 } 199 endif; 200 201 /** 202 * Internal compat function to mimic mb_ord(). 203 * 204 * @ignore 205 * @since 7.1.0 206 * 207 * @param string $string Return the code point at the start of this string. 208 * @param "UTF-8"|null $encoding Must be 'UTF-8' or null. 209 * @return int|false The Unicode code point for the first character of string or false on failure. 210 */ 211 function _mb_ord( $string, $encoding = null ) { 212 if ( ! is_string( $string ) || '' === $string || ( isset( $encoding ) && 'UTF-8' !== $encoding ) ) { 213 return false; 214 } 215 216 $byte_length = 0; 217 $invalid_length = 0; 218 $found_count = _wp_scan_utf8( $string, $byte_length, $invalid_length, null, 1 ); 219 220 if ( 1 !== $found_count ) { 221 return false; 222 } 223 224 // These are valid code points, so no further validation is required. 225 $b0 = ord( $string[0] ); 226 227 switch ( $byte_length ) { 228 case 1: 229 return $b0; 230 231 case 2: 232 return ( 233 ( ( $b0 & 0x1F ) << 6 ) | 234 ( ( ord( $string[1] ) & 0x3F ) ) 235 ); 236 237 case 3: 238 return ( 239 ( ( $b0 & 0x0F ) << 12 ) | 240 ( ( ord( $string[1] ) & 0x3F ) << 6 ) | 241 ( ( ord( $string[2] ) & 0x3F ) ) 242 ); 243 244 case 4: 245 return ( 246 ( ( $b0 & 0x07 ) << 18 ) | 247 ( ( ord( $string[1] ) & 0x3F ) << 12 ) | 248 ( ( ord( $string[2] ) & 0x3F ) << 6 ) | 249 ( ( ord( $string[3] ) & 0x3F ) ) 250 ); 251 } 252 253 return false; 254 } 255 256 if ( ! function_exists( 'mb_substr' ) ) : 257 /** 258 * Compat function to mimic mb_substr(). 259 * 260 * @ignore 261 * @since 3.2.0 262 * 263 * @see _mb_substr() 264 * 265 * @param string $string The string to extract the substring from. 266 * @param int $start Position to being extraction from in `$string`. 267 * @param int|null $length Optional. Maximum number of characters to extract from `$string`. 268 * Default null. 269 * @param string|null $encoding Optional. Character encoding to use. Default null. 270 * @return string Extracted substring. 271 */ 272 function mb_substr( $string, $start, $length = null, $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound 273 return _mb_substr( $string, $start, $length, $encoding ); 274 } 275 endif; 276 277 /** 278 * Internal compat function to mimic mb_substr(). 279 * 280 * Only supports UTF-8 and non-shifting single-byte encodings. For all other encodings 281 * expect the substrings to be misaligned. When the given encoding (or the `blog_charset` 282 * if none is provided) isn’t UTF-8 then the function returns the output of {@see \substr()}. 283 * 284 * @ignore 285 * @since 3.2.0 286 * 287 * @param string $str The string to extract the substring from. 288 * @param int $start Character offset at which to start the substring extraction. 289 * @param int|null $length Optional. Maximum number of characters to extract from `$str`. 290 * Default null. 291 * @param string|null $encoding Optional. Character encoding to use. Default null. 292 * @return string Extracted substring. 293 */ 294 function _mb_substr( $str, $start, $length = null, $encoding = null ) { 295 if ( null === $str ) { 296 return ''; 297 } 298 299 // The solution below works only for UTF-8; treat all other encodings as byte streams. 300 if ( ! _is_utf8_charset( $encoding ?? get_option( 'blog_charset' ) ) ) { 301 $result = is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length ); 302 303 /* 304 * For an out-of-range start, substr() returns false on PHP < 8.0 but an 305 * empty string on PHP >= 8.0. mb_substr() always returns an empty string, 306 * so normalize to match its behavior across all supported PHP versions. 307 */ 308 return false === $result ? '' : $result; 309 } 310 311 $total_length = ( $start < 0 || $length < 0 ) 312 ? _wp_utf8_codepoint_count( $str ) 313 : 0; 314 315 $normalized_start = $start < 0 316 ? max( 0, $total_length + $start ) 317 : $start; 318 319 /* 320 * The starting offset is provided as characters, which means this needs to 321 * find how many bytes that many characters occupies at the start of the string. 322 */ 323 $starting_byte_offset = _wp_utf8_codepoint_span( $str, 0, $normalized_start ); 324 325 $normalized_length = $length < 0 326 ? max( 0, $total_length - $normalized_start + $length ) 327 : $length; 328 329 /* 330 * This is the main step. It finds how many bytes the given length of code points 331 * occupies in the input, starting at the byte offset calculated above. 332 */ 333 $byte_length = isset( $normalized_length ) 334 ? _wp_utf8_codepoint_span( $str, $starting_byte_offset, $normalized_length ) 335 : ( strlen( $str ) - $starting_byte_offset ); 336 337 // The result is a normal byte-level substring using the computed ranges. 338 return substr( $str, $starting_byte_offset, $byte_length ); 339 } 340 341 if ( ! function_exists( 'mb_strlen' ) ) : 342 /** 343 * Compat function to mimic mb_strlen(). 344 * 345 * @ignore 346 * @since 4.2.0 347 * 348 * @see _mb_strlen() 349 * 350 * @param string $string The string to retrieve the character length from. 351 * @param string|null $encoding Optional. Character encoding to use. Default null. 352 * @return int String length of `$string`. 353 */ 354 function mb_strlen( $string, $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound 355 return _mb_strlen( $string, $encoding ); 356 } 357 endif; 358 359 /** 360 * Internal compat function to mimic mb_strlen(). 361 * 362 * Only supports UTF-8 and non-shifting single-byte encodings. For all other 363 * encodings expect the counts to be wrong. When the given encoding (or the 364 * `blog_charset` if none is provided) isn’t UTF-8 then the function returns 365 * the byte-count of the provided string. 366 * 367 * @ignore 368 * @since 4.2.0 369 * 370 * @param string $str The string to retrieve the character length from. 371 * @param string|null $encoding Optional. Count characters according to this encoding. 372 * Default is to consult `blog_charset`. 373 * @return int Count of code points if UTF-8, byte length otherwise. 374 */ 375 function _mb_strlen( $str, $encoding = null ) { 376 return _is_utf8_charset( $encoding ?? get_option( 'blog_charset' ) ) 377 ? _wp_utf8_codepoint_count( $str ) 378 : strlen( $str ); 379 } 380 381 if ( ! function_exists( 'utf8_encode' ) ) : 382 if ( extension_loaded( 'mbstring' ) ) : 383 /** 384 * Converts a string from ISO-8859-1 to UTF-8. 385 * 386 * @deprecated Use {@see \mb_convert_encoding()} instead. 387 * 388 * @since 6.9.0 389 * 390 * @param string $iso_8859_1_text Text treated as ISO-8859-1 (latin1) bytes. 391 * @return string Text converted into a UTF-8. 392 */ 393 function utf8_encode( $iso_8859_1_text ): string { 394 _deprecated_function( __FUNCTION__, '6.9.0', 'mb_convert_encoding' ); 395 396 return mb_convert_encoding( $iso_8859_1_text, 'UTF-8', 'ISO-8859-1' ); 397 } 398 399 else : 400 /** 401 * @ignore 402 * @private 403 * 404 * @since 6.9.0 405 */ 406 function utf8_encode( $iso_8859_1_text ): string { 407 _deprecated_function( __FUNCTION__, '6.9.0', 'mb_convert_encoding' ); 408 409 return _wp_utf8_encode_fallback( $iso_8859_1_text ); 410 } 411 412 endif; 413 endif; 414 415 if ( ! function_exists( 'utf8_decode' ) ) : 416 if ( extension_loaded( 'mbstring' ) ) : 417 /** 418 * Converts a string from UTF-8 to ISO-8859-1. 419 * 420 * @deprecated Use {@see \mb_convert_encoding()} instead. 421 * 422 * @since 6.9.0 423 * 424 * @param string $utf8_text Text treated as UTF-8. 425 * @return string Text converted into ISO-8859-1. 426 */ 427 function utf8_decode( $utf8_text ): string { 428 _deprecated_function( __FUNCTION__, '6.9.0', 'mb_convert_encoding' ); 429 430 return mb_convert_encoding( $utf8_text, 'ISO-8859-1', 'UTF-8' ); 431 } 432 433 else : 434 /** 435 * @ignore 436 * @private 437 * 438 * @since 6.9.0 439 */ 440 function utf8_decode( $utf8_text ): string { 441 _deprecated_function( __FUNCTION__, '6.9.0', 'mb_convert_encoding' ); 442 443 return _wp_utf8_decode_fallback( $utf8_text ); 444 } 445 446 endif; 447 endif; 448 449 // sodium_crypto_box() was introduced with Sodium in PHP 7.2, but the extension may not be enabled. 450 if ( ! function_exists( 'sodium_crypto_box' ) ) { 451 require ABSPATH . WPINC . '/sodium_compat/autoload.php'; 452 } 453 454 if ( ! function_exists( 'array_is_list' ) ) { 455 /** 456 * Polyfill for `array_is_list()` function added in PHP 8.1. 457 * 458 * Determines if the given array is a list. 459 * 460 * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. 461 * 462 * @see https://github.com/symfony/polyfill-php81/tree/main 463 * 464 * @since 6.5.0 465 * 466 * @param array<mixed> $arr The array being evaluated. 467 * @return bool True if array is a list, false otherwise. 468 */ 469 function array_is_list( $arr ) { 470 if ( ( array() === $arr ) || ( array_values( $arr ) === $arr ) ) { 471 return true; 472 } 473 474 $next_key = -1; 475 476 foreach ( $arr as $k => $v ) { 477 if ( ++$next_key !== $k ) { 478 return false; 479 } 480 } 481 482 return true; 483 } 484 } 485 486 if ( ! function_exists( 'str_contains' ) ) { 487 /** 488 * Polyfill for `str_contains()` function added in PHP 8.0. 489 * 490 * Performs a case-sensitive check indicating if needle is 491 * contained in haystack. 492 * 493 * @since 5.9.0 494 * 495 * @param string $haystack The string to search in. 496 * @param string $needle The substring to search for in the `$haystack`. 497 * @return bool True if `$needle` is in `$haystack`, otherwise false. 498 */ 499 function str_contains( $haystack, $needle ) { 500 if ( '' === $needle ) { 501 return true; 502 } 503 504 return false !== strpos( $haystack, $needle ); 505 } 506 } 507 508 if ( ! function_exists( 'str_starts_with' ) ) { 509 /** 510 * Polyfill for `str_starts_with()` function added in PHP 8.0. 511 * 512 * Performs a case-sensitive check indicating if 513 * the haystack begins with needle. 514 * 515 * @since 5.9.0 516 * 517 * @param string $haystack The string to search in. 518 * @param string $needle The substring to search for in the `$haystack`. 519 * @return bool True if `$haystack` starts with `$needle`, otherwise false. 520 */ 521 function str_starts_with( $haystack, $needle ) { 522 if ( '' === $needle ) { 523 return true; 524 } 525 526 return 0 === strpos( $haystack, $needle ); 527 } 528 } 529 530 if ( ! function_exists( 'str_ends_with' ) ) { 531 /** 532 * Polyfill for `str_ends_with()` function added in PHP 8.0. 533 * 534 * Performs a case-sensitive check indicating if 535 * the haystack ends with needle. 536 * 537 * @since 5.9.0 538 * 539 * @param string $haystack The string to search in. 540 * @param string $needle The substring to search for in the `$haystack`. 541 * @return bool True if `$haystack` ends with `$needle`, otherwise false. 542 */ 543 function str_ends_with( $haystack, $needle ) { 544 if ( '' === $haystack ) { 545 return '' === $needle; 546 } 547 548 $len = strlen( $needle ); 549 550 return substr( $haystack, -$len, $len ) === $needle; 551 } 552 } 553 554 if ( ! function_exists( 'array_find' ) ) { 555 /** 556 * Polyfill for `array_find()` function added in PHP 8.4. 557 * 558 * Searches an array for the first element that passes a given callback. 559 * 560 * @since 6.8.0 561 * 562 * @param array $array The array to search. 563 * @param callable $callback The callback to run for each element. 564 * @return mixed|null The first element in the array that passes the `$callback`, otherwise null. 565 */ 566 function array_find( array $array, callable $callback ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 567 foreach ( $array as $key => $value ) { 568 if ( $callback( $value, $key ) ) { 569 return $value; 570 } 571 } 572 573 return null; 574 } 575 } 576 577 if ( ! function_exists( 'array_find_key' ) ) { 578 /** 579 * Polyfill for `array_find_key()` function added in PHP 8.4. 580 * 581 * Searches an array for the first key that passes a given callback. 582 * 583 * @since 6.8.0 584 * 585 * @param array $array The array to search. 586 * @param callable $callback The callback to run for each element. 587 * @return int|string|null The first key in the array that passes the `$callback`, otherwise null. 588 */ 589 function array_find_key( array $array, callable $callback ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 590 foreach ( $array as $key => $value ) { 591 if ( $callback( $value, $key ) ) { 592 return $key; 593 } 594 } 595 596 return null; 597 } 598 } 599 600 if ( ! function_exists( 'array_any' ) ) { 601 /** 602 * Polyfill for `array_any()` function added in PHP 8.4. 603 * 604 * Checks if any element of an array passes a given callback. 605 * 606 * @since 6.8.0 607 * 608 * @param array $array The array to check. 609 * @param callable $callback The callback to run for each element. 610 * @return bool True if any element in the array passes the `$callback`, otherwise false. 611 */ 612 function array_any( array $array, callable $callback ): bool { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 613 foreach ( $array as $key => $value ) { 614 if ( $callback( $value, $key ) ) { 615 return true; 616 } 617 } 618 619 return false; 620 } 621 } 622 623 if ( ! function_exists( 'array_all' ) ) { 624 /** 625 * Polyfill for `array_all()` function added in PHP 8.4. 626 * 627 * Checks if all elements of an array pass a given callback. 628 * 629 * @since 6.8.0 630 * 631 * @param array $array The array to check. 632 * @param callable $callback The callback to run for each element. 633 * @return bool True if all elements in the array pass the `$callback`, otherwise false. 634 */ 635 function array_all( array $array, callable $callback ): bool { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 636 foreach ( $array as $key => $value ) { 637 if ( ! $callback( $value, $key ) ) { 638 return false; 639 } 640 } 641 642 return true; 643 } 644 } 645 646 if ( ! function_exists( 'array_first' ) ) { 647 /** 648 * Polyfill for `array_first()` function added in PHP 8.5. 649 * 650 * Returns the first element of an array. 651 * 652 * @since 6.9.0 653 * 654 * @param array $array The array to get the first element from. 655 * @return mixed|null The first element of the array, or null if the array is empty. 656 */ 657 function array_first( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 658 if ( empty( $array ) ) { 659 return null; 660 } 661 662 foreach ( $array as $value ) { 663 return $value; 664 } 665 } 666 } 667 668 if ( ! function_exists( 'array_last' ) ) { 669 /** 670 * Polyfill for `array_last()` function added in PHP 8.5. 671 * 672 * Returns the last element of an array. 673 * 674 * @since 6.9.0 675 * 676 * @param array $array The array to get the last element from. 677 * @return mixed|null The last element of the array, or null if the array is empty. 678 */ 679 function array_last( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 680 if ( empty( $array ) ) { 681 return null; 682 } 683 684 return $array[ array_key_last( $array ) ]; 685 } 686 } 687 688 // IMAGETYPE_AVIF constant is only defined in PHP 8.x or later. 689 if ( ! defined( 'IMAGETYPE_AVIF' ) ) { 690 define( 'IMAGETYPE_AVIF', 19 ); 691 } 692 693 // IMG_AVIF constant is only defined in PHP 8.x or later. 694 if ( ! defined( 'IMG_AVIF' ) ) { 695 define( 'IMG_AVIF', IMAGETYPE_AVIF ); 696 } 697 698 // IMAGETYPE_HEIF constant is only defined in PHP 8.5 or later. 699 if ( ! defined( 'IMAGETYPE_HEIF' ) ) { 700 define( 'IMAGETYPE_HEIF', 20 ); 701 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sat Jul 4 08:20:12 2026 | Cross-referenced by PHPXref |