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