[ 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 * @access private 37 * 38 * @param bool $set - Used for testing only 39 * null : default - get PCRE/u capability 40 * false : Used for testing - return false for future calls to this function 41 * 'reset': Used for testing - restore default behavior of this function 42 */ 43 function _wp_can_use_pcre_u( $set = null ) { 44 static $utf8_pcre = 'reset'; 45 46 if ( null !== $set ) { 47 $utf8_pcre = $set; 48 } 49 50 if ( 'reset' === $utf8_pcre ) { 51 $utf8_pcre = true; 52 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 72 restore_error_handler(); 73 } 74 75 return $utf8_pcre; 76 } 77 78 /** 79 * Indicates if a given slug for a character set represents the UTF-8 text encoding. 80 * 81 * A charset is considered to represent UTF-8 if it is a case-insensitive match 82 * of "UTF-8" with or without the hyphen. 83 * 84 * Example: 85 * 86 * true === _is_utf8_charset( 'UTF-8' ); 87 * true === _is_utf8_charset( 'utf8' ); 88 * false === _is_utf8_charset( 'latin1' ); 89 * false === _is_utf8_charset( 'UTF 8' ); 90 * 91 * // Only strings match. 92 * false === _is_utf8_charset( [ 'charset' => 'utf-8' ] ); 93 * 94 * `is_utf8_charset` should be used outside of this file. 95 * 96 * @ignore 97 * @since 6.6.1 98 * 99 * @param string $charset_slug Slug representing a text character encoding, or "charset". 100 * E.g. "UTF-8", "Windows-1252", "ISO-8859-1", "SJIS". 101 * 102 * @return bool Whether the slug represents the UTF-8 encoding. 103 */ 104 function _is_utf8_charset( $charset_slug ) { 105 if ( ! is_string( $charset_slug ) ) { 106 return false; 107 } 108 109 return ( 110 0 === strcasecmp( 'UTF-8', $charset_slug ) || 111 0 === strcasecmp( 'UTF8', $charset_slug ) 112 ); 113 } 114 115 if ( ! function_exists( 'mb_substr' ) ) : 116 /** 117 * Compat function to mimic mb_substr(). 118 * 119 * @ignore 120 * @since 3.2.0 121 * 122 * @see _mb_substr() 123 * 124 * @param string $string The string to extract the substring from. 125 * @param int $start Position to being extraction from in `$string`. 126 * @param int|null $length Optional. Maximum number of characters to extract from `$string`. 127 * Default null. 128 * @param string|null $encoding Optional. Character encoding to use. Default null. 129 * @return string Extracted substring. 130 */ 131 function mb_substr( $string, $start, $length = null, $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound 132 return _mb_substr( $string, $start, $length, $encoding ); 133 } 134 endif; 135 136 /** 137 * Internal compat function to mimic mb_substr(). 138 * 139 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. 140 * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte 141 * sequence. The behavior of this function for invalid inputs is undefined. 142 * 143 * @ignore 144 * @since 3.2.0 145 * 146 * @param string $str The string to extract the substring from. 147 * @param int $start Position to being extraction from in `$str`. 148 * @param int|null $length Optional. Maximum number of characters to extract from `$str`. 149 * Default null. 150 * @param string|null $encoding Optional. Character encoding to use. Default null. 151 * @return string Extracted substring. 152 */ 153 function _mb_substr( $str, $start, $length = null, $encoding = null ) { 154 if ( null === $str ) { 155 return ''; 156 } 157 158 if ( null === $encoding ) { 159 $encoding = get_option( 'blog_charset' ); 160 } 161 162 /* 163 * The solution below works only for UTF-8, so in case of a different 164 * charset just use built-in substr(). 165 */ 166 if ( ! _is_utf8_charset( $encoding ) ) { 167 return is_null( $length ) ? substr( $str, $start ) : substr( $str, $start, $length ); 168 } 169 170 if ( _wp_can_use_pcre_u() ) { 171 // Use the regex unicode support to separate the UTF-8 characters into an array. 172 preg_match_all( '/./us', $str, $match ); 173 $chars = is_null( $length ) ? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length ); 174 return implode( '', $chars ); 175 } 176 177 $regex = '/( 178 [\x00-\x7F] # single-byte sequences 0xxxxxxx 179 | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx 180 | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 181 | [\xE1-\xEC][\x80-\xBF]{2} 182 | \xED[\x80-\x9F][\x80-\xBF] 183 | [\xEE-\xEF][\x80-\xBF]{2} 184 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 185 | [\xF1-\xF3][\x80-\xBF]{3} 186 | \xF4[\x80-\x8F][\x80-\xBF]{2} 187 )/x'; 188 189 // Start with 1 element instead of 0 since the first thing we do is pop. 190 $chars = array( '' ); 191 192 do { 193 // We had some string left over from the last round, but we counted it in that last round. 194 array_pop( $chars ); 195 196 /* 197 * Split by UTF-8 character, limit to 1000 characters (last array element will contain 198 * the rest of the string). 199 */ 200 $pieces = preg_split( $regex, $str, 1000, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY ); 201 202 $chars = array_merge( $chars, $pieces ); 203 204 // If there's anything left over, repeat the loop. 205 } while ( count( $pieces ) > 1 && $str = array_pop( $pieces ) ); 206 207 return implode( '', array_slice( $chars, $start, $length ) ); 208 } 209 210 if ( ! function_exists( 'mb_strlen' ) ) : 211 /** 212 * Compat function to mimic mb_strlen(). 213 * 214 * @ignore 215 * @since 4.2.0 216 * 217 * @see _mb_strlen() 218 * 219 * @param string $string The string to retrieve the character length from. 220 * @param string|null $encoding Optional. Character encoding to use. Default null. 221 * @return int String length of `$string`. 222 */ 223 function mb_strlen( $string, $encoding = null ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.stringFound 224 return _mb_strlen( $string, $encoding ); 225 } 226 endif; 227 228 /** 229 * Internal compat function to mimic mb_strlen(). 230 * 231 * Only understands UTF-8 and 8bit. All other character sets will be treated as 8bit. 232 * For `$encoding === UTF-8`, the `$str` input is expected to be a valid UTF-8 byte 233 * sequence. The behavior of this function for invalid inputs is undefined. 234 * 235 * @ignore 236 * @since 4.2.0 237 * 238 * @param string $str The string to retrieve the character length from. 239 * @param string|null $encoding Optional. Character encoding to use. Default null. 240 * @return int String length of `$str`. 241 */ 242 function _mb_strlen( $str, $encoding = null ) { 243 if ( null === $encoding ) { 244 $encoding = get_option( 'blog_charset' ); 245 } 246 247 /* 248 * The solution below works only for UTF-8, so in case of a different charset 249 * just use built-in strlen(). 250 */ 251 if ( ! _is_utf8_charset( $encoding ) ) { 252 return strlen( $str ); 253 } 254 255 if ( _wp_can_use_pcre_u() ) { 256 // Use the regex unicode support to separate the UTF-8 characters into an array. 257 preg_match_all( '/./us', $str, $match ); 258 return count( $match[0] ); 259 } 260 261 $regex = '/(?: 262 [\x00-\x7F] # single-byte sequences 0xxxxxxx 263 | [\xC2-\xDF][\x80-\xBF] # double-byte sequences 110xxxxx 10xxxxxx 264 | \xE0[\xA0-\xBF][\x80-\xBF] # triple-byte sequences 1110xxxx 10xxxxxx * 2 265 | [\xE1-\xEC][\x80-\xBF]{2} 266 | \xED[\x80-\x9F][\x80-\xBF] 267 | [\xEE-\xEF][\x80-\xBF]{2} 268 | \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences 11110xxx 10xxxxxx * 3 269 | [\xF1-\xF3][\x80-\xBF]{3} 270 | \xF4[\x80-\x8F][\x80-\xBF]{2} 271 )/x'; 272 273 // Start at 1 instead of 0 since the first thing we do is decrement. 274 $count = 1; 275 276 do { 277 // We had some string left over from the last round, but we counted it in that last round. 278 --$count; 279 280 /* 281 * Split by UTF-8 character, limit to 1000 characters (last array element will contain 282 * the rest of the string). 283 */ 284 $pieces = preg_split( $regex, $str, 1000 ); 285 286 // Increment. 287 $count += count( $pieces ); 288 289 // If there's anything left over, repeat the loop. 290 } while ( $str = array_pop( $pieces ) ); 291 292 // Fencepost: preg_split() always returns one extra item in the array. 293 return --$count; 294 } 295 296 // sodium_crypto_box() was introduced in PHP 7.2. 297 if ( ! function_exists( 'sodium_crypto_box' ) ) { 298 require ABSPATH . WPINC . '/sodium_compat/autoload.php'; 299 } 300 301 if ( ! function_exists( 'is_countable' ) ) { 302 /** 303 * Polyfill for is_countable() function added in PHP 7.3. 304 * 305 * Verify that the content of a variable is an array or an object 306 * implementing the Countable interface. 307 * 308 * @since 4.9.6 309 * 310 * @param mixed $value The value to check. 311 * @return bool True if `$value` is countable, false otherwise. 312 */ 313 function is_countable( $value ) { 314 return ( is_array( $value ) 315 || $value instanceof Countable 316 || $value instanceof SimpleXMLElement 317 || $value instanceof ResourceBundle 318 ); 319 } 320 } 321 322 if ( ! function_exists( 'array_key_first' ) ) { 323 /** 324 * Polyfill for array_key_first() function added in PHP 7.3. 325 * 326 * Get the first key of the given array without affecting 327 * the internal array pointer. 328 * 329 * @since 5.9.0 330 * 331 * @param array $array An array. 332 * @return string|int|null The first key of array if the array 333 * is not empty; `null` otherwise. 334 */ 335 function array_key_first( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 336 if ( empty( $array ) ) { 337 return null; 338 } 339 340 foreach ( $array as $key => $value ) { 341 return $key; 342 } 343 } 344 } 345 346 if ( ! function_exists( 'array_key_last' ) ) { 347 /** 348 * Polyfill for `array_key_last()` function added in PHP 7.3. 349 * 350 * Get the last key of the given array without affecting the 351 * internal array pointer. 352 * 353 * @since 5.9.0 354 * 355 * @param array $array An array. 356 * @return string|int|null The last key of array if the array 357 *. is not empty; `null` otherwise. 358 */ 359 function array_key_last( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 360 if ( empty( $array ) ) { 361 return null; 362 } 363 364 end( $array ); 365 366 return key( $array ); 367 } 368 } 369 370 if ( ! function_exists( 'array_is_list' ) ) { 371 /** 372 * Polyfill for `array_is_list()` function added in PHP 8.1. 373 * 374 * Determines if the given array is a list. 375 * 376 * An array is considered a list if its keys consist of consecutive numbers from 0 to count($array)-1. 377 * 378 * @see https://github.com/symfony/polyfill-php81/tree/main 379 * 380 * @since 6.5.0 381 * 382 * @param array<mixed> $arr The array being evaluated. 383 * @return bool True if array is a list, false otherwise. 384 */ 385 function array_is_list( $arr ) { 386 if ( ( array() === $arr ) || ( array_values( $arr ) === $arr ) ) { 387 return true; 388 } 389 390 $next_key = -1; 391 392 foreach ( $arr as $k => $v ) { 393 if ( ++$next_key !== $k ) { 394 return false; 395 } 396 } 397 398 return true; 399 } 400 } 401 402 if ( ! function_exists( 'str_contains' ) ) { 403 /** 404 * Polyfill for `str_contains()` function added in PHP 8.0. 405 * 406 * Performs a case-sensitive check indicating if needle is 407 * contained in haystack. 408 * 409 * @since 5.9.0 410 * 411 * @param string $haystack The string to search in. 412 * @param string $needle The substring to search for in the `$haystack`. 413 * @return bool True if `$needle` is in `$haystack`, otherwise false. 414 */ 415 function str_contains( $haystack, $needle ) { 416 if ( '' === $needle ) { 417 return true; 418 } 419 420 return false !== strpos( $haystack, $needle ); 421 } 422 } 423 424 if ( ! function_exists( 'str_starts_with' ) ) { 425 /** 426 * Polyfill for `str_starts_with()` function added in PHP 8.0. 427 * 428 * Performs a case-sensitive check indicating if 429 * the haystack begins with needle. 430 * 431 * @since 5.9.0 432 * 433 * @param string $haystack The string to search in. 434 * @param string $needle The substring to search for in the `$haystack`. 435 * @return bool True if `$haystack` starts with `$needle`, otherwise false. 436 */ 437 function str_starts_with( $haystack, $needle ) { 438 if ( '' === $needle ) { 439 return true; 440 } 441 442 return 0 === strpos( $haystack, $needle ); 443 } 444 } 445 446 if ( ! function_exists( 'str_ends_with' ) ) { 447 /** 448 * Polyfill for `str_ends_with()` function added in PHP 8.0. 449 * 450 * Performs a case-sensitive check indicating if 451 * the haystack ends with needle. 452 * 453 * @since 5.9.0 454 * 455 * @param string $haystack The string to search in. 456 * @param string $needle The substring to search for in the `$haystack`. 457 * @return bool True if `$haystack` ends with `$needle`, otherwise false. 458 */ 459 function str_ends_with( $haystack, $needle ) { 460 if ( '' === $haystack ) { 461 return '' === $needle; 462 } 463 464 $len = strlen( $needle ); 465 466 return substr( $haystack, -$len, $len ) === $needle; 467 } 468 } 469 470 if ( ! function_exists( 'array_find' ) ) { 471 /** 472 * Polyfill for `array_find()` function added in PHP 8.4. 473 * 474 * Searches an array for the first element that passes a given callback. 475 * 476 * @since 6.8.0 477 * 478 * @param array $array The array to search. 479 * @param callable $callback The callback to run for each element. 480 * @return mixed|null The first element in the array that passes the `$callback`, otherwise null. 481 */ 482 function array_find( array $array, callable $callback ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 483 foreach ( $array as $key => $value ) { 484 if ( $callback( $value, $key ) ) { 485 return $value; 486 } 487 } 488 489 return null; 490 } 491 } 492 493 if ( ! function_exists( 'array_find_key' ) ) { 494 /** 495 * Polyfill for `array_find_key()` function added in PHP 8.4. 496 * 497 * Searches an array for the first key that passes a given callback. 498 * 499 * @since 6.8.0 500 * 501 * @param array $array The array to search. 502 * @param callable $callback The callback to run for each element. 503 * @return int|string|null The first key in the array that passes the `$callback`, otherwise null. 504 */ 505 function array_find_key( array $array, callable $callback ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 506 foreach ( $array as $key => $value ) { 507 if ( $callback( $value, $key ) ) { 508 return $key; 509 } 510 } 511 512 return null; 513 } 514 } 515 516 if ( ! function_exists( 'array_any' ) ) { 517 /** 518 * Polyfill for `array_any()` function added in PHP 8.4. 519 * 520 * Checks if any element of an array passes a given callback. 521 * 522 * @since 6.8.0 523 * 524 * @param array $array The array to check. 525 * @param callable $callback The callback to run for each element. 526 * @return bool True if any element in the array passes the `$callback`, otherwise false. 527 */ 528 function array_any( array $array, callable $callback ): bool { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 529 foreach ( $array as $key => $value ) { 530 if ( $callback( $value, $key ) ) { 531 return true; 532 } 533 } 534 535 return false; 536 } 537 } 538 539 if ( ! function_exists( 'array_all' ) ) { 540 /** 541 * Polyfill for `array_all()` function added in PHP 8.4. 542 * 543 * Checks if all elements of an array pass a given callback. 544 * 545 * @since 6.8.0 546 * 547 * @param array $array The array to check. 548 * @param callable $callback The callback to run for each element. 549 * @return bool True if all elements in the array pass the `$callback`, otherwise false. 550 */ 551 function array_all( array $array, callable $callback ): bool { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 552 foreach ( $array as $key => $value ) { 553 if ( ! $callback( $value, $key ) ) { 554 return false; 555 } 556 } 557 558 return true; 559 } 560 } 561 562 if ( ! function_exists( 'array_first' ) ) { 563 /** 564 * Polyfill for `array_first()` function added in PHP 8.5. 565 * 566 * Returns the first element of an array. 567 * 568 * @since 6.9.0 569 * 570 * @param array $array The array to get the first element from. 571 * @return mixed|null The first element of the array, or null if the array is empty. 572 */ 573 function array_first( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 574 if ( empty( $array ) ) { 575 return null; 576 } 577 578 foreach ( $array as $value ) { 579 return $value; 580 } 581 } 582 } 583 584 if ( ! function_exists( 'array_last' ) ) { 585 /** 586 * Polyfill for `array_last()` function added in PHP 8.5. 587 * 588 * Returns the last element of an array. 589 * 590 * @since 6.9.0 591 * 592 * @param array $array The array to get the last element from. 593 * @return mixed|null The last element of the array, or null if the array is empty. 594 */ 595 function array_last( array $array ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.arrayFound 596 if ( empty( $array ) ) { 597 return null; 598 } 599 600 return $array[ array_key_last( $array ) ]; 601 } 602 } 603 604 // IMAGETYPE_AVIF constant is only defined in PHP 8.x or later. 605 if ( ! defined( 'IMAGETYPE_AVIF' ) ) { 606 define( 'IMAGETYPE_AVIF', 19 ); 607 } 608 609 // IMG_AVIF constant is only defined in PHP 8.x or later. 610 if ( ! defined( 'IMG_AVIF' ) ) { 611 define( 'IMG_AVIF', IMAGETYPE_AVIF ); 612 } 613 614 // IMAGETYPE_HEIC constant is not yet defined in PHP as of PHP 8.3. 615 if ( ! defined( 'IMAGETYPE_HEIC' ) ) { 616 define( 'IMAGETYPE_HEIC', 99 ); 617 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Thu Sep 4 08:20:02 2025 | Cross-referenced by PHPXref |