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