wp/wp-includes/functions.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
equal deleted inserted replaced
18:be944660c56a 19:3d72ae0968f4
     8 require ABSPATH . WPINC . '/option.php';
     8 require ABSPATH . WPINC . '/option.php';
     9 
     9 
    10 /**
    10 /**
    11  * Convert given MySQL date string into a different format.
    11  * Convert given MySQL date string into a different format.
    12  *
    12  *
    13  * `$format` should be a PHP date format string.
    13  *  - `$format` should be a PHP date format string.
    14  * 'U' and 'G' formats will return a sum of timestamp with timezone offset.
    14  *  - 'U' and 'G' formats will return an integer sum of timestamp with timezone offset.
    15  * `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`).
    15  *  - `$date` is expected to be local time in MySQL format (`Y-m-d H:i:s`).
    16  *
    16  *
    17  * Historically UTC time could be passed to the function to produce Unix timestamp.
    17  * Historically UTC time could be passed to the function to produce Unix timestamp.
    18  *
    18  *
    19  * If `$translate` is true then the given date and format string will
    19  * If `$translate` is true then the given date and format string will
    20  * be passed to `wp_date()` for translation.
    20  * be passed to `wp_date()` for translation.
    22  * @since 0.71
    22  * @since 0.71
    23  *
    23  *
    24  * @param string $format    Format of the date to return.
    24  * @param string $format    Format of the date to return.
    25  * @param string $date      Date string to convert.
    25  * @param string $date      Date string to convert.
    26  * @param bool   $translate Whether the return date should be translated. Default true.
    26  * @param bool   $translate Whether the return date should be translated. Default true.
    27  * @return string|int|false Formatted date string or sum of Unix timestamp and timezone offset.
    27  * @return string|int|false Integer if `$format` is 'U' or 'G', string otherwise.
    28  *                          False on failure.
    28  *                          False on failure.
    29  */
    29  */
    30 function mysql2date( $format, $date, $translate = true ) {
    30 function mysql2date( $format, $date, $translate = true ) {
    31 	if ( empty( $date ) ) {
    31 	if ( empty( $date ) ) {
    32 		return false;
    32 		return false;
    51 }
    51 }
    52 
    52 
    53 /**
    53 /**
    54  * Retrieves the current time based on specified type.
    54  * Retrieves the current time based on specified type.
    55  *
    55  *
    56  * The 'mysql' type will return the time in the format for MySQL DATETIME field.
    56  *  - The 'mysql' type will return the time in the format for MySQL DATETIME field.
    57  * The 'timestamp' type will return the current timestamp or a sum of timestamp
    57  *  - The 'timestamp' or 'U' types will return the current timestamp or a sum of timestamp
    58  * and timezone offset, depending on `$gmt`.
    58  *    and timezone offset, depending on `$gmt`.
    59  * Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d').
    59  *  - Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d').
    60  *
    60  *
    61  * If $gmt is set to either '1' or 'true', then both types will use GMT time.
    61  * If `$gmt` is a truthy value then both types will use GMT time, otherwise the
    62  * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
    62  * output is adjusted with the GMT offset for the site.
    63  *
    63  *
    64  * @since 1.0.0
    64  * @since 1.0.0
    65  *
    65  * @since 5.3.0 Now returns an integer if `$type` is 'U'. Previously a string was returned.
    66  * @param string   $type Type of time to retrieve. Accepts 'mysql', 'timestamp',
    66  *
       
    67  * @param string   $type Type of time to retrieve. Accepts 'mysql', 'timestamp', 'U',
    67  *                       or PHP date format string (e.g. 'Y-m-d').
    68  *                       or PHP date format string (e.g. 'Y-m-d').
    68  * @param int|bool $gmt  Optional. Whether to use GMT timezone. Default false.
    69  * @param int|bool $gmt  Optional. Whether to use GMT timezone. Default false.
    69  * @return int|string Integer if $type is 'timestamp', string otherwise.
    70  * @return int|string Integer if `$type` is 'timestamp' or 'U', string otherwise.
    70  */
    71  */
    71 function current_time( $type, $gmt = 0 ) {
    72 function current_time( $type, $gmt = 0 ) {
    72 	// Don't use non-GMT timestamp, unless you know the difference and really need to.
    73 	// Don't use non-GMT timestamp, unless you know the difference and really need to.
    73 	if ( 'timestamp' === $type || 'U' === $type ) {
    74 	if ( 'timestamp' === $type || 'U' === $type ) {
    74 		return $gmt ? time() : time() + (int) ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
    75 		return $gmt ? time() : time() + (int) ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
    83 
    84 
    84 	return $datetime->format( $type );
    85 	return $datetime->format( $type );
    85 }
    86 }
    86 
    87 
    87 /**
    88 /**
    88  * Retrieves the current time as an object with the timezone from settings.
    89  * Retrieves the current time as an object using the site's timezone.
    89  *
    90  *
    90  * @since 5.3.0
    91  * @since 5.3.0
    91  *
    92  *
    92  * @return DateTimeImmutable Date and time object.
    93  * @return DateTimeImmutable Date and time object.
    93  */
    94  */
    94 function current_datetime() {
    95 function current_datetime() {
    95 	return new DateTimeImmutable( 'now', wp_timezone() );
    96 	return new DateTimeImmutable( 'now', wp_timezone() );
    96 }
    97 }
    97 
    98 
    98 /**
    99 /**
    99  * Retrieves the timezone from site settings as a string.
   100  * Retrieves the timezone of the site as a string.
   100  *
   101  *
   101  * Uses the `timezone_string` option to get a proper timezone if available,
   102  * Uses the `timezone_string` option to get a proper timezone name if available,
   102  * otherwise falls back to an offset.
   103  * otherwise falls back to a manual UTC ± offset.
       
   104  *
       
   105  * Example return values:
       
   106  *
       
   107  *  - 'Europe/Rome'
       
   108  *  - 'America/North_Dakota/New_Salem'
       
   109  *  - 'UTC'
       
   110  *  - '-06:30'
       
   111  *  - '+00:00'
       
   112  *  - '+08:45'
   103  *
   113  *
   104  * @since 5.3.0
   114  * @since 5.3.0
   105  *
   115  *
   106  * @return string PHP timezone string or a ±HH:MM offset.
   116  * @return string PHP timezone name or a ±HH:MM offset.
   107  */
   117  */
   108 function wp_timezone_string() {
   118 function wp_timezone_string() {
   109 	$timezone_string = get_option( 'timezone_string' );
   119 	$timezone_string = get_option( 'timezone_string' );
   110 
   120 
   111 	if ( $timezone_string ) {
   121 	if ( $timezone_string ) {
   123 
   133 
   124 	return $tz_offset;
   134 	return $tz_offset;
   125 }
   135 }
   126 
   136 
   127 /**
   137 /**
   128  * Retrieves the timezone from site settings as a `DateTimeZone` object.
   138  * Retrieves the timezone of the site as a `DateTimeZone` object.
   129  *
   139  *
   130  * Timezone can be based on a PHP timezone string or a ±HH:MM offset.
   140  * Timezone can be based on a PHP timezone string or a ±HH:MM offset.
   131  *
   141  *
   132  * @since 5.3.0
   142  * @since 5.3.0
   133  *
   143  *
   165 function date_i18n( $format, $timestamp_with_offset = false, $gmt = false ) {
   175 function date_i18n( $format, $timestamp_with_offset = false, $gmt = false ) {
   166 	$timestamp = $timestamp_with_offset;
   176 	$timestamp = $timestamp_with_offset;
   167 
   177 
   168 	// If timestamp is omitted it should be current time (summed with offset, unless `$gmt` is true).
   178 	// If timestamp is omitted it should be current time (summed with offset, unless `$gmt` is true).
   169 	if ( ! is_numeric( $timestamp ) ) {
   179 	if ( ! is_numeric( $timestamp ) ) {
       
   180 		// phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested
   170 		$timestamp = current_time( 'timestamp', $gmt );
   181 		$timestamp = current_time( 'timestamp', $gmt );
   171 	}
   182 	}
   172 
   183 
   173 	/*
   184 	/*
   174 	 * This is a legacy implementation quirk that the returned timestamp is also with offset.
   185 	 * This is a legacy implementation quirk that the returned timestamp is also with offset.
   215  *
   226  *
   216  * Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed
   227  * Note that, unlike `date_i18n()`, this function accepts a true Unix timestamp, not summed
   217  * with timezone offset.
   228  * with timezone offset.
   218  *
   229  *
   219  * @since 5.3.0
   230  * @since 5.3.0
       
   231  *
       
   232  * @global WP_Locale $wp_locale WordPress date and time locale object.
   220  *
   233  *
   221  * @param string       $format    PHP date format.
   234  * @param string       $format    PHP date format.
   222  * @param int          $timestamp Optional. Unix timestamp. Defaults to current time.
   235  * @param int          $timestamp Optional. Unix timestamp. Defaults to current time.
   223  * @param DateTimeZone $timezone  Optional. Timezone to output result in. Defaults to timezone
   236  * @param DateTimeZone $timezone  Optional. Timezone to output result in. Defaults to timezone
   224  *                                from site settings.
   237  *                                from site settings.
   426 	 */
   439 	 */
   427 	return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );
   440 	return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );
   428 }
   441 }
   429 
   442 
   430 /**
   443 /**
   431  * Convert number of bytes largest unit bytes will fit into.
   444  * Converts a number of bytes to the largest unit the bytes will fit into.
   432  *
   445  *
   433  * It is easier to read 1 KB than 1024 bytes and 1 MB than 1048576 bytes. Converts
   446  * It is easier to read 1 KB than 1024 bytes and 1 MB than 1048576 bytes. Converts
   434  * number of bytes to human readable number by taking the number of that unit
   447  * number of bytes to human readable number by taking the number of that unit
   435  * that the bytes will go into it. Supports TB value.
   448  * that the bytes will go into it. Supports YB value.
   436  *
   449  *
   437  * Please note that integers in PHP are limited to 32 bits, unless they are on
   450  * Please note that integers in PHP are limited to 32 bits, unless they are on
   438  * 64 bit architecture, then they have 64 bit size. If you need to place the
   451  * 64 bit architecture, then they have 64 bit size. If you need to place the
   439  * larger size then what PHP integer type will hold, then use a string. It will
   452  * larger size then what PHP integer type will hold, then use a string. It will
   440  * be converted to a double, which should always have 64 bit length.
   453  * be converted to a double, which should always have 64 bit length.
   441  *
   454  *
   442  * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
   455  * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
   443  *
   456  *
   444  * @since 2.3.0
   457  * @since 2.3.0
       
   458  * @since 6.0.0 Support for PB, EB, ZB, and YB was added.
   445  *
   459  *
   446  * @param int|string $bytes    Number of bytes. Note max integer size for integers.
   460  * @param int|string $bytes    Number of bytes. Note max integer size for integers.
   447  * @param int        $decimals Optional. Precision of number of decimal places. Default 0.
   461  * @param int        $decimals Optional. Precision of number of decimal places. Default 0.
   448  * @return string|false Number string on success, false on failure.
   462  * @return string|false Number string on success, false on failure.
   449  */
   463  */
   450 function size_format( $bytes, $decimals = 0 ) {
   464 function size_format( $bytes, $decimals = 0 ) {
   451 	$quant = array(
   465 	$quant = array(
       
   466 		/* translators: Unit symbol for yottabyte. */
       
   467 		_x( 'YB', 'unit symbol' ) => YB_IN_BYTES,
       
   468 		/* translators: Unit symbol for zettabyte. */
       
   469 		_x( 'ZB', 'unit symbol' ) => ZB_IN_BYTES,
       
   470 		/* translators: Unit symbol for exabyte. */
       
   471 		_x( 'EB', 'unit symbol' ) => EB_IN_BYTES,
       
   472 		/* translators: Unit symbol for petabyte. */
       
   473 		_x( 'PB', 'unit symbol' ) => PB_IN_BYTES,
   452 		/* translators: Unit symbol for terabyte. */
   474 		/* translators: Unit symbol for terabyte. */
   453 		_x( 'TB', 'unit symbol' ) => TB_IN_BYTES,
   475 		_x( 'TB', 'unit symbol' ) => TB_IN_BYTES,
   454 		/* translators: Unit symbol for gigabyte. */
   476 		/* translators: Unit symbol for gigabyte. */
   455 		_x( 'GB', 'unit symbol' ) => GB_IN_BYTES,
   477 		_x( 'GB', 'unit symbol' ) => GB_IN_BYTES,
   456 		/* translators: Unit symbol for megabyte. */
   478 		/* translators: Unit symbol for megabyte. */
   550  *
   572  *
   551  * @since 0.71
   573  * @since 0.71
   552  *
   574  *
   553  * @param string     $mysqlstring   Date or datetime field type from MySQL.
   575  * @param string     $mysqlstring   Date or datetime field type from MySQL.
   554  * @param int|string $start_of_week Optional. Start of the week as an integer. Default empty string.
   576  * @param int|string $start_of_week Optional. Start of the week as an integer. Default empty string.
   555  * @return array Keys are 'start' and 'end'.
   577  * @return int[] {
       
   578  *     Week start and end dates as Unix timestamps.
       
   579  *
       
   580  *     @type int $start The week start date as a Unix timestamp.
       
   581  *     @type int $end   The week end date as a Unix timestamp.
       
   582  * }
   556  */
   583  */
   557 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
   584 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
   558 	// MySQL string year.
   585 	// MySQL string year.
   559 	$my = substr( $mysqlstring, 0, 4 );
   586 	$my = substr( $mysqlstring, 0, 4 );
   560 
   587 
   791 
   818 
   792 /**
   819 /**
   793  * Use RegEx to extract URLs from arbitrary content.
   820  * Use RegEx to extract URLs from arbitrary content.
   794  *
   821  *
   795  * @since 3.7.0
   822  * @since 3.7.0
       
   823  * @since 6.0.0 Fixes support for HTML entities (Trac 30580).
   796  *
   824  *
   797  * @param string $content Content to extract URLs from.
   825  * @param string $content Content to extract URLs from.
   798  * @return string[] Array of URLs found in passed string.
   826  * @return string[] Array of URLs found in passed string.
   799  */
   827  */
   800 function wp_extract_urls( $content ) {
   828 function wp_extract_urls( $content ) {
   804 			. '[^\s()<>]+'
   832 			. '[^\s()<>]+'
   805 			. '[.]'
   833 			. '[.]'
   806 			. '(?:'
   834 			. '(?:'
   807 				. '\([\w\d]+\)|'
   835 				. '\([\w\d]+\)|'
   808 				. '(?:'
   836 				. '(?:'
   809 					. "[^`!()\[\]{};:'\".,<>«»“”‘’\s]|"
   837 					. "[^`!()\[\]{}:'\".,<>«»“”‘’\s]|"
   810 					. '(?:[:]\d+)?/?'
   838 					. '(?:[:]\d+)?/?'
   811 				. ')+'
   839 				. ')+'
   812 			. ')'
   840 			. ')'
   813 		. ")\\1#",
   841 		. ")\\1#",
   814 		$content,
   842 		$content,
   815 		$post_links
   843 		$post_links
   816 	);
   844 	);
   817 
   845 
   818 	$post_links = array_unique( array_map( 'html_entity_decode', $post_links[2] ) );
   846 	$post_links = array_unique(
       
   847 		array_map(
       
   848 			static function( $link ) {
       
   849 				// Decode to replace valid entities, like &amp;.
       
   850 				$link = html_entity_decode( $link );
       
   851 				// Maintain backward compatibility by removing extraneous semi-colons (`;`).
       
   852 				return str_replace( ';', '', $link );
       
   853 			},
       
   854 			$post_links[2]
       
   855 		)
       
   856 	);
   819 
   857 
   820 	return array_values( $post_links );
   858 	return array_values( $post_links );
   821 }
   859 }
   822 
   860 
   823 /**
   861 /**
  1149 	$ret = build_query( $qs );
  1187 	$ret = build_query( $qs );
  1150 	$ret = trim( $ret, '?' );
  1188 	$ret = trim( $ret, '?' );
  1151 	$ret = preg_replace( '#=(&|$)#', '$1', $ret );
  1189 	$ret = preg_replace( '#=(&|$)#', '$1', $ret );
  1152 	$ret = $protocol . $base . $ret . $frag;
  1190 	$ret = $protocol . $base . $ret . $frag;
  1153 	$ret = rtrim( $ret, '?' );
  1191 	$ret = rtrim( $ret, '?' );
       
  1192 	$ret = str_replace( '?#', '#', $ret );
  1154 	return $ret;
  1193 	return $ret;
  1155 }
  1194 }
  1156 
  1195 
  1157 /**
  1196 /**
  1158  * Removes an item or items from a query string.
  1197  * Removes an item or items from a query string.
  1528  * Must be 'y' to be true.
  1567  * Must be 'y' to be true.
  1529  *
  1568  *
  1530  * @since 1.0.0
  1569  * @since 1.0.0
  1531  *
  1570  *
  1532  * @param string $yn Character string containing either 'y' (yes) or 'n' (no).
  1571  * @param string $yn Character string containing either 'y' (yes) or 'n' (no).
  1533  * @return bool True if yes, false on anything else.
  1572  * @return bool True if 'y', false on anything else.
  1534  */
  1573  */
  1535 function bool_from_yn( $yn ) {
  1574 function bool_from_yn( $yn ) {
  1536 	return ( 'y' === strtolower( $yn ) );
  1575 	return ( 'y' === strtolower( $yn ) );
  1537 }
  1576 }
  1538 
  1577 
  1559 	if ( '' === $feed || 'feed' === $feed ) {
  1598 	if ( '' === $feed || 'feed' === $feed ) {
  1560 		$feed = get_default_feed();
  1599 		$feed = get_default_feed();
  1561 	}
  1600 	}
  1562 
  1601 
  1563 	if ( ! has_action( "do_feed_{$feed}" ) ) {
  1602 	if ( ! has_action( "do_feed_{$feed}" ) ) {
  1564 		wp_die( __( 'Error: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
  1603 		wp_die( __( '<strong>Error</strong>: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
  1565 	}
  1604 	}
  1566 
  1605 
  1567 	/**
  1606 	/**
  1568 	 * Fires once the given feed is loaded.
  1607 	 * Fires once the given feed is loaded.
  1569 	 *
  1608 	 *
  2119 		list( $wrapper, $path ) = explode( '://', $path, 2 );
  2158 		list( $wrapper, $path ) = explode( '://', $path, 2 );
  2120 
  2159 
  2121 		$wrapper .= '://';
  2160 		$wrapper .= '://';
  2122 	}
  2161 	}
  2123 
  2162 
  2124 	// Standardise all paths to use '/'.
  2163 	// Standardize all paths to use '/'.
  2125 	$path = str_replace( '\\', '/', $path );
  2164 	$path = str_replace( '\\', '/', $path );
  2126 
  2165 
  2127 	// Replace multiple slashes down to a singular, allowing for network shares having two slashes.
  2166 	// Replace multiple slashes down to a singular, allowing for network shares having two slashes.
  2128 	$path = preg_replace( '|(?<=.)/+|', '/', $path );
  2167 	$path = preg_replace( '|(?<=.)/+|', '/', $path );
  2129 
  2168 
  2517 
  2556 
  2518 			// At this point the file name may not be unique. This is tested below and the $number is incremented.
  2557 			// At this point the file name may not be unique. This is tested below and the $number is incremented.
  2519 			$filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename );
  2558 			$filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename );
  2520 		}
  2559 		}
  2521 
  2560 
  2522 		// Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext()
  2561 		/*
  2523 		// in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here.
  2562 		 * Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext()
       
  2563 		 * in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here.
       
  2564 		 */
  2524 		$file_type = wp_check_filetype( $filename );
  2565 		$file_type = wp_check_filetype( $filename );
  2525 		$mime_type = $file_type['type'];
  2566 		$mime_type = $file_type['type'];
  2526 
  2567 
  2527 		$is_image    = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) );
  2568 		$is_image    = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) );
  2528 		$upload_dir  = wp_get_upload_dir();
  2569 		$upload_dir  = wp_get_upload_dir();
  2529 		$lc_filename = null;
  2570 		$lc_filename = null;
  2530 
  2571 
  2531 		$lc_ext = strtolower( $ext );
  2572 		$lc_ext = strtolower( $ext );
  2532 		$_dir   = trailingslashit( $dir );
  2573 		$_dir   = trailingslashit( $dir );
  2533 
  2574 
  2534 		// If the extension is uppercase add an alternate file name with lowercase extension. Both need to be tested
  2575 		/*
  2535 		// for uniqueness as the extension will be changed to lowercase for better compatibility with different filesystems.
  2576 		 * If the extension is uppercase add an alternate file name with lowercase extension.
  2536 		// Fixes an inconsistency in WP < 2.9 where uppercase extensions were allowed but image sub-sizes were created with
  2577 		 * Both need to be tested for uniqueness as the extension will be changed to lowercase
  2537 		// lowercase extensions.
  2578 		 * for better compatibility with different filesystems. Fixes an inconsistency in WP < 2.9
       
  2579 		 * where uppercase extensions were allowed but image sub-sizes were created with
       
  2580 		 * lowercase extensions.
       
  2581 		 */
  2538 		if ( $ext && $lc_ext !== $ext ) {
  2582 		if ( $ext && $lc_ext !== $ext ) {
  2539 			$lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|', $lc_ext, $filename );
  2583 			$lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|', $lc_ext, $filename );
  2540 		}
  2584 		}
  2541 
  2585 
  2542 		// Increment the number added to the file name if there are any files in $dir whose names match one of the
  2586 		/*
  2543 		// possible name variations.
  2587 		 * Increment the number added to the file name if there are any files in $dir
       
  2588 		 * whose names match one of the possible name variations.
       
  2589 		 */
  2544 		while ( file_exists( $_dir . $filename ) || ( $lc_filename && file_exists( $_dir . $lc_filename ) ) ) {
  2590 		while ( file_exists( $_dir . $filename ) || ( $lc_filename && file_exists( $_dir . $lc_filename ) ) ) {
  2545 			$new_number = (int) $number + 1;
  2591 			$new_number = (int) $number + 1;
  2546 
  2592 
  2547 			if ( $lc_filename ) {
  2593 			if ( $lc_filename ) {
  2548 				$lc_filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $lc_filename );
  2594 				$lc_filename = str_replace(
       
  2595 					array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ),
       
  2596 					"-{$new_number}{$lc_ext}",
       
  2597 					$lc_filename
       
  2598 				);
  2549 			}
  2599 			}
  2550 
  2600 
  2551 			if ( '' === "{$number}{$ext}" ) {
  2601 			if ( '' === "{$number}{$ext}" ) {
  2552 				$filename = "{$filename}-{$new_number}";
  2602 				$filename = "{$filename}-{$new_number}";
  2553 			} else {
  2603 			} else {
  2554 				$filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename );
  2604 				$filename = str_replace(
       
  2605 					array( "-{$number}{$ext}", "{$number}{$ext}" ),
       
  2606 					"-{$new_number}{$ext}",
       
  2607 					$filename
       
  2608 				);
  2555 			}
  2609 			}
  2556 
  2610 
  2557 			$number = $new_number;
  2611 			$number = $new_number;
  2558 		}
  2612 		}
  2559 
  2613 
  2560 		// Change the extension to lowercase if needed.
  2614 		// Change the extension to lowercase if needed.
  2561 		if ( $lc_filename ) {
  2615 		if ( $lc_filename ) {
  2562 			$filename = $lc_filename;
  2616 			$filename = $lc_filename;
  2563 		}
  2617 		}
  2564 
  2618 
  2565 		// Prevent collisions with existing file names that contain dimension-like strings
  2619 		/*
  2566 		// (whether they are subsizes or originals uploaded prior to #42437).
  2620 		 * Prevent collisions with existing file names that contain dimension-like strings
       
  2621 		 * (whether they are subsizes or originals uploaded prior to #42437).
       
  2622 		 */
  2567 
  2623 
  2568 		$files = array();
  2624 		$files = array();
  2569 		$count = 10000;
  2625 		$count = 10000;
  2570 
  2626 
  2571 		// The (resized) image files would have name and extension, and will be in the uploads dir.
  2627 		// The (resized) image files would have name and extension, and will be in the uploads dir.
  2596 			}
  2652 			}
  2597 
  2653 
  2598 			if ( ! empty( $files ) ) {
  2654 			if ( ! empty( $files ) ) {
  2599 				$count = count( $files );
  2655 				$count = count( $files );
  2600 
  2656 
  2601 				// Ensure this never goes into infinite loop
  2657 				/*
  2602 				// as it uses pathinfo() and regex in the check, but string replacement for the changes.
  2658 				 * Ensure this never goes into infinite loop as it uses pathinfo() and regex in the check,
       
  2659 				 * but string replacement for the changes.
       
  2660 				 */
  2603 				$i = 0;
  2661 				$i = 0;
  2604 
  2662 
  2605 				while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) {
  2663 				while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) {
  2606 					$new_number = (int) $number + 1;
  2664 					$new_number = (int) $number + 1;
  2607 
  2665 
  2608 					// If $ext is uppercase it was replaced with the lowercase version after the previous loop.
  2666 					// If $ext is uppercase it was replaced with the lowercase version after the previous loop.
  2609 					$filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename );
  2667 					$filename = str_replace(
       
  2668 						array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ),
       
  2669 						"-{$new_number}{$lc_ext}",
       
  2670 						$filename
       
  2671 					);
  2610 
  2672 
  2611 					$number = $new_number;
  2673 					$number = $new_number;
  2612 					$i++;
  2674 					$i++;
  2613 				}
  2675 				}
  2614 			}
  2676 			}
  2615 		}
  2677 		}
  2616 
  2678 
  2617 		// Check if an image will be converted after uploading or some existing images sub-sizes file names may conflict
  2679 		/*
  2618 		// when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes.
  2680 		 * Check if an image will be converted after uploading or some existing image sub-size file names may conflict
       
  2681 		 * when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes.
       
  2682 		 */
  2619 		if ( $is_image ) {
  2683 		if ( $is_image ) {
       
  2684 			/** This filter is documented in wp-includes/class-wp-image-editor.php */
  2620 			$output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type );
  2685 			$output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type );
  2621 			$alt_types      = array();
  2686 			$alt_types      = array();
  2622 
  2687 
  2623 			if ( ! empty( $output_formats[ $mime_type ] ) ) {
  2688 			if ( ! empty( $output_formats[ $mime_type ] ) ) {
  2624 				// The image will be converted to this format/mime type.
  2689 				// The image will be converted to this format/mime type.
  2646 
  2711 
  2647 				$alt_filenames[ $alt_ext ] = $alt_filename;
  2712 				$alt_filenames[ $alt_ext ] = $alt_filename;
  2648 			}
  2713 			}
  2649 
  2714 
  2650 			if ( ! empty( $alt_filenames ) ) {
  2715 			if ( ! empty( $alt_filenames ) ) {
  2651 				// Add the original filename. It needs to be checked again together with the alternate filenames
  2716 				/*
  2652 				// when $number is incremented.
  2717 				 * Add the original filename. It needs to be checked again
       
  2718 				 * together with the alternate filenames when $number is incremented.
       
  2719 				 */
  2653 				$alt_filenames[ $lc_ext ] = $filename;
  2720 				$alt_filenames[ $lc_ext ] = $filename;
  2654 
  2721 
  2655 				// Ensure no infinite loop.
  2722 				// Ensure no infinite loop.
  2656 				$i = 0;
  2723 				$i = 0;
  2657 
  2724 
  2658 				while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames, $_dir, $files ) ) {
  2725 				while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames, $_dir, $files ) ) {
  2659 					$new_number = (int) $number + 1;
  2726 					$new_number = (int) $number + 1;
  2660 
  2727 
  2661 					foreach ( $alt_filenames as $alt_ext => $alt_filename ) {
  2728 					foreach ( $alt_filenames as $alt_ext => $alt_filename ) {
  2662 						$alt_filenames[ $alt_ext ] = str_replace( array( "-{$number}{$alt_ext}", "{$number}{$alt_ext}" ), "-{$new_number}{$alt_ext}", $alt_filename );
  2729 						$alt_filenames[ $alt_ext ] = str_replace(
       
  2730 							array( "-{$number}{$alt_ext}", "{$number}{$alt_ext}" ),
       
  2731 							"-{$new_number}{$alt_ext}",
       
  2732 							$alt_filename
       
  2733 						);
  2663 					}
  2734 					}
  2664 
  2735 
  2665 					// Also update the $number in (the output) $filename.
  2736 					/*
  2666 					// If the extension was uppercase it was already replaced with the lowercase version.
  2737 					 * Also update the $number in (the output) $filename.
  2667 					$filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename );
  2738 					 * If the extension was uppercase it was already replaced with the lowercase version.
       
  2739 					 */
       
  2740 					$filename = str_replace(
       
  2741 						array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ),
       
  2742 						"-{$new_number}{$lc_ext}",
       
  2743 						$filename
       
  2744 					);
  2668 
  2745 
  2669 					$number = $new_number;
  2746 					$number = $new_number;
  2670 					$i++;
  2747 					$i++;
  2671 				}
  2748 				}
  2672 			}
  2749 			}
  2678 	 *
  2755 	 *
  2679 	 * @since 4.5.0
  2756 	 * @since 4.5.0
  2680 	 * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added.
  2757 	 * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added.
  2681 	 *
  2758 	 *
  2682 	 * @param string        $filename                 Unique file name.
  2759 	 * @param string        $filename                 Unique file name.
  2683 	 * @param string        $ext                      File extension, eg. ".png".
  2760 	 * @param string        $ext                      File extension. Example: ".png".
  2684 	 * @param string        $dir                      Directory path.
  2761 	 * @param string        $dir                      Directory path.
  2685 	 * @param callable|null $unique_filename_callback Callback function that generates the unique file name.
  2762 	 * @param callable|null $unique_filename_callback Callback function that generates the unique file name.
  2686 	 * @param string[]      $alt_filenames            Array of alternate file names that were checked for collisions.
  2763 	 * @param string[]      $alt_filenames            Array of alternate file names that were checked for collisions.
  2687 	 * @param int|string    $number                   The highest number that was used to make the file name unique
  2764 	 * @param int|string    $number                   The highest number that was used to make the file name unique
  2688 	 *                                                or an empty string if unused.
  2765 	 *                                                or an empty string if unused.
  2788 		return array( 'error' => __( 'Empty filename' ) );
  2865 		return array( 'error' => __( 'Empty filename' ) );
  2789 	}
  2866 	}
  2790 
  2867 
  2791 	$wp_filetype = wp_check_filetype( $name );
  2868 	$wp_filetype = wp_check_filetype( $name );
  2792 	if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) ) {
  2869 	if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) ) {
  2793 		return array( 'error' => __( 'Sorry, this file type is not permitted for security reasons.' ) );
  2870 		return array( 'error' => __( 'Sorry, you are not allowed to upload this file type.' ) );
  2794 	}
  2871 	}
  2795 
  2872 
  2796 	$upload = wp_upload_dir( $time );
  2873 	$upload = wp_upload_dir( $time );
  2797 
  2874 
  2798 	if ( false !== $upload['error'] ) {
  2875 	if ( false !== $upload['error'] ) {
  3178  * @return string|false The actual mime type or false if the type cannot be determined.
  3255  * @return string|false The actual mime type or false if the type cannot be determined.
  3179  */
  3256  */
  3180 function wp_get_image_mime( $file ) {
  3257 function wp_get_image_mime( $file ) {
  3181 	/*
  3258 	/*
  3182 	 * Use exif_imagetype() to check the mimetype if available or fall back to
  3259 	 * Use exif_imagetype() to check the mimetype if available or fall back to
  3183 	 * getimagesize() if exif isn't avaialbe. If either function throws an Exception
  3260 	 * getimagesize() if exif isn't available. If either function throws an Exception
  3184 	 * we assume the file could not be validated.
  3261 	 * we assume the file could not be validated.
  3185 	 */
  3262 	 */
  3186 	try {
  3263 	try {
  3187 		if ( is_callable( 'exif_imagetype' ) ) {
  3264 		if ( is_callable( 'exif_imagetype' ) ) {
  3188 			$imagetype = exif_imagetype( $file );
  3265 			$imagetype = exif_imagetype( $file );
  3206 
  3283 
  3207 		if ( false !== $mime ) {
  3284 		if ( false !== $mime ) {
  3208 			return $mime;
  3285 			return $mime;
  3209 		}
  3286 		}
  3210 
  3287 
  3211 		$handle = fopen( $file, 'rb' );
  3288 		$magic = file_get_contents( $file, false, null, 0, 12 );
  3212 		if ( false === $handle ) {
  3289 
  3213 			return false;
       
  3214 		}
       
  3215 
       
  3216 		$magic = fread( $handle, 12 );
       
  3217 		if ( false === $magic ) {
  3290 		if ( false === $magic ) {
  3218 			return false;
  3291 			return false;
  3219 		}
  3292 		}
  3220 
  3293 
  3221 		/*
  3294 		/*
  3230 			// WEBP.
  3303 			// WEBP.
  3231 			( 16 === strpos( $magic, '57454250' ) )
  3304 			( 16 === strpos( $magic, '57454250' ) )
  3232 		) {
  3305 		) {
  3233 			$mime = 'image/webp';
  3306 			$mime = 'image/webp';
  3234 		}
  3307 		}
  3235 
       
  3236 		fclose( $handle );
       
  3237 	} catch ( Exception $e ) {
  3308 	} catch ( Exception $e ) {
  3238 		$mime = false;
  3309 		$mime = false;
  3239 	}
  3310 	}
  3240 
  3311 
  3241 	return $mime;
  3312 	return $mime;
  3406 		)
  3477 		)
  3407 	);
  3478 	);
  3408 }
  3479 }
  3409 
  3480 
  3410 /**
  3481 /**
       
  3482  * Wrapper for PHP filesize with filters and casting the result as an integer.
       
  3483  *
       
  3484  * @since 6.0.0
       
  3485  *
       
  3486  * @link https://www.php.net/manual/en/function.filesize.php
       
  3487  *
       
  3488  * @param string $path Path to the file.
       
  3489  * @return int The size of the file in bytes, or 0 in the event of an error.
       
  3490  */
       
  3491 function wp_filesize( $path ) {
       
  3492 	/**
       
  3493 	 * Filters the result of wp_filesize before the PHP function is run.
       
  3494 	 *
       
  3495 	 * @since 6.0.0
       
  3496 	 *
       
  3497 	 * @param null|int $size The unfiltered value. Returning an int from the callback bypasses the filesize call.
       
  3498 	 * @param string   $path Path to the file.
       
  3499 	 */
       
  3500 	$size = apply_filters( 'pre_wp_filesize', null, $path );
       
  3501 
       
  3502 	if ( is_int( $size ) ) {
       
  3503 		return $size;
       
  3504 	}
       
  3505 
       
  3506 	$size = file_exists( $path ) ? (int) filesize( $path ) : 0;
       
  3507 
       
  3508 	/**
       
  3509 	 * Filters the size of the file.
       
  3510 	 *
       
  3511 	 * @since 6.0.0
       
  3512 	 *
       
  3513 	 * @param int    $size The result of PHP filesize on the file.
       
  3514 	 * @param string $path Path to the file.
       
  3515 	 */
       
  3516 	return (int) apply_filters( 'wp_filesize', $size, $path );
       
  3517 }
       
  3518 
       
  3519 /**
  3411  * Retrieve list of allowed mime types and file extensions.
  3520  * Retrieve list of allowed mime types and file extensions.
  3412  *
  3521  *
  3413  * @since 2.8.6
  3522  * @since 2.8.6
  3414  *
  3523  *
  3415  * @param int|WP_User $user Optional. User to check. Defaults to current user.
  3524  * @param int|WP_User $user Optional. User to check. Defaults to current user.
  3448  * @since 2.0.4
  3557  * @since 2.0.4
  3449  *
  3558  *
  3450  * @param string $action The nonce action.
  3559  * @param string $action The nonce action.
  3451  */
  3560  */
  3452 function wp_nonce_ays( $action ) {
  3561 function wp_nonce_ays( $action ) {
       
  3562 	// Default title and response code.
       
  3563 	$title         = __( 'Something went wrong.' );
       
  3564 	$response_code = 403;
       
  3565 
  3453 	if ( 'log-out' === $action ) {
  3566 	if ( 'log-out' === $action ) {
  3454 		$html = sprintf(
  3567 		$title = sprintf(
  3455 			/* translators: %s: Site title. */
  3568 			/* translators: %s: Site title. */
  3456 			__( 'You are attempting to log out of %s' ),
  3569 			__( 'You are attempting to log out of %s' ),
  3457 			get_bloginfo( 'name' )
  3570 			get_bloginfo( 'name' )
  3458 		);
  3571 		);
       
  3572 		$html        = $title;
  3459 		$html       .= '</p><p>';
  3573 		$html       .= '</p><p>';
  3460 		$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
  3574 		$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
  3461 		$html       .= sprintf(
  3575 		$html       .= sprintf(
  3462 			/* translators: %s: Logout URL. */
  3576 			/* translators: %s: Logout URL. */
  3463 			__( 'Do you really want to <a href="%s">log out</a>?' ),
  3577 			__( 'Do you really want to <a href="%s">log out</a>?' ),
  3473 				__( 'Please try again.' )
  3587 				__( 'Please try again.' )
  3474 			);
  3588 			);
  3475 		}
  3589 		}
  3476 	}
  3590 	}
  3477 
  3591 
  3478 	wp_die( $html, __( 'Something went wrong.' ), 403 );
  3592 	wp_die( $html, $title, $response_code );
  3479 }
  3593 }
  3480 
  3594 
  3481 /**
  3595 /**
  3482  * Kills WordPress execution and displays HTML page with an error message.
  3596  * Kills WordPress execution and displays HTML page with an error message.
  3483  *
  3597  *
  3540 		/**
  3654 		/**
  3541 		 * Filters the callback for killing WordPress execution for Ajax requests.
  3655 		 * Filters the callback for killing WordPress execution for Ajax requests.
  3542 		 *
  3656 		 *
  3543 		 * @since 3.4.0
  3657 		 * @since 3.4.0
  3544 		 *
  3658 		 *
  3545 		 * @param callable $function Callback function name.
  3659 		 * @param callable $callback Callback function name.
  3546 		 */
  3660 		 */
  3547 		$function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
  3661 		$callback = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
  3548 	} elseif ( wp_is_json_request() ) {
  3662 	} elseif ( wp_is_json_request() ) {
  3549 		/**
  3663 		/**
  3550 		 * Filters the callback for killing WordPress execution for JSON requests.
  3664 		 * Filters the callback for killing WordPress execution for JSON requests.
  3551 		 *
  3665 		 *
  3552 		 * @since 5.1.0
  3666 		 * @since 5.1.0
  3553 		 *
  3667 		 *
  3554 		 * @param callable $function Callback function name.
  3668 		 * @param callable $callback Callback function name.
  3555 		 */
  3669 		 */
  3556 		$function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
  3670 		$callback = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
  3557 	} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST && wp_is_jsonp_request() ) {
  3671 	} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST && wp_is_jsonp_request() ) {
  3558 		/**
  3672 		/**
  3559 		 * Filters the callback for killing WordPress execution for JSONP REST requests.
  3673 		 * Filters the callback for killing WordPress execution for JSONP REST requests.
  3560 		 *
  3674 		 *
  3561 		 * @since 5.2.0
  3675 		 * @since 5.2.0
  3562 		 *
  3676 		 *
  3563 		 * @param callable $function Callback function name.
  3677 		 * @param callable $callback Callback function name.
  3564 		 */
  3678 		 */
  3565 		$function = apply_filters( 'wp_die_jsonp_handler', '_jsonp_wp_die_handler' );
  3679 		$callback = apply_filters( 'wp_die_jsonp_handler', '_jsonp_wp_die_handler' );
  3566 	} elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
  3680 	} elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
  3567 		/**
  3681 		/**
  3568 		 * Filters the callback for killing WordPress execution for XML-RPC requests.
  3682 		 * Filters the callback for killing WordPress execution for XML-RPC requests.
  3569 		 *
  3683 		 *
  3570 		 * @since 3.4.0
  3684 		 * @since 3.4.0
  3571 		 *
  3685 		 *
  3572 		 * @param callable $function Callback function name.
  3686 		 * @param callable $callback Callback function name.
  3573 		 */
  3687 		 */
  3574 		$function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
  3688 		$callback = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
  3575 	} elseif ( wp_is_xml_request()
  3689 	} elseif ( wp_is_xml_request()
  3576 		|| isset( $wp_query ) &&
  3690 		|| isset( $wp_query ) &&
  3577 			( function_exists( 'is_feed' ) && is_feed()
  3691 			( function_exists( 'is_feed' ) && is_feed()
  3578 			|| function_exists( 'is_comment_feed' ) && is_comment_feed()
  3692 			|| function_exists( 'is_comment_feed' ) && is_comment_feed()
  3579 			|| function_exists( 'is_trackback' ) && is_trackback() ) ) {
  3693 			|| function_exists( 'is_trackback' ) && is_trackback() ) ) {
  3580 		/**
  3694 		/**
  3581 		 * Filters the callback for killing WordPress execution for XML requests.
  3695 		 * Filters the callback for killing WordPress execution for XML requests.
  3582 		 *
  3696 		 *
  3583 		 * @since 5.2.0
  3697 		 * @since 5.2.0
  3584 		 *
  3698 		 *
  3585 		 * @param callable $function Callback function name.
  3699 		 * @param callable $callback Callback function name.
  3586 		 */
  3700 		 */
  3587 		$function = apply_filters( 'wp_die_xml_handler', '_xml_wp_die_handler' );
  3701 		$callback = apply_filters( 'wp_die_xml_handler', '_xml_wp_die_handler' );
  3588 	} else {
  3702 	} else {
  3589 		/**
  3703 		/**
  3590 		 * Filters the callback for killing WordPress execution for all non-Ajax, non-JSON, non-XML requests.
  3704 		 * Filters the callback for killing WordPress execution for all non-Ajax, non-JSON, non-XML requests.
  3591 		 *
  3705 		 *
  3592 		 * @since 3.0.0
  3706 		 * @since 3.0.0
  3593 		 *
  3707 		 *
  3594 		 * @param callable $function Callback function name.
  3708 		 * @param callable $callback Callback function name.
  3595 		 */
  3709 		 */
  3596 		$function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
  3710 		$callback = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
  3597 	}
  3711 	}
  3598 
  3712 
  3599 	call_user_func( $function, $message, $title, $args );
  3713 	call_user_func( $callback, $message, $title, $args );
  3600 }
  3714 }
  3601 
  3715 
  3602 /**
  3716 /**
  3603  * Kills WordPress execution and displays HTML page with an error message.
  3717  * Kills WordPress execution and displays HTML page with an error message.
  3604  *
  3718  *
  4391 
  4505 
  4392 	return 0 === $illegal_char_count;
  4506 	return 0 === $illegal_char_count;
  4393 }
  4507 }
  4394 
  4508 
  4395 /**
  4509 /**
       
  4510  * Reads and decodes a JSON file.
       
  4511  *
       
  4512  * @since 5.9.0
       
  4513  *
       
  4514  * @param string $filename Path to the JSON file.
       
  4515  * @param array  $options  {
       
  4516  *     Optional. Options to be used with `json_decode()`.
       
  4517  *
       
  4518  *     @type bool $associative Optional. When `true`, JSON objects will be returned as associative arrays.
       
  4519  *                             When `false`, JSON objects will be returned as objects.
       
  4520  * }
       
  4521  *
       
  4522  * @return mixed Returns the value encoded in JSON in appropriate PHP type.
       
  4523  *               `null` is returned if the file is not found, or its content can't be decoded.
       
  4524  */
       
  4525 function wp_json_file_decode( $filename, $options = array() ) {
       
  4526 	$result   = null;
       
  4527 	$filename = wp_normalize_path( realpath( $filename ) );
       
  4528 	if ( ! file_exists( $filename ) ) {
       
  4529 		trigger_error(
       
  4530 			sprintf(
       
  4531 				/* translators: %s: Path to the JSON file. */
       
  4532 				__( "File %s doesn't exist!" ),
       
  4533 				$filename
       
  4534 			)
       
  4535 		);
       
  4536 		return $result;
       
  4537 	}
       
  4538 
       
  4539 	$options      = wp_parse_args( $options, array( 'associative' => false ) );
       
  4540 	$decoded_file = json_decode( file_get_contents( $filename ), $options['associative'] );
       
  4541 
       
  4542 	if ( JSON_ERROR_NONE !== json_last_error() ) {
       
  4543 		trigger_error(
       
  4544 			sprintf(
       
  4545 				/* translators: 1: Path to the JSON file, 2: Error message. */
       
  4546 				__( 'Error when decoding a JSON file at path %1$s: %2$s' ),
       
  4547 				$filename,
       
  4548 				json_last_error_msg()
       
  4549 			)
       
  4550 		);
       
  4551 		return $result;
       
  4552 	}
       
  4553 
       
  4554 	return $decoded_file;
       
  4555 }
       
  4556 
       
  4557 /**
  4396  * Retrieve the WordPress home page URL.
  4558  * Retrieve the WordPress home page URL.
  4397  *
  4559  *
  4398  * If the constant named 'WP_HOME' exists, then it will be used and returned
  4560  * If the constant named 'WP_HOME' exists, then it will be used and returned
  4399  * by the function. This can be used to counter the redirection on your local
  4561  * by the function. This can be used to counter the redirection on your local
  4400  * development environment.
  4562  * development environment.
  4425  * @access private
  4587  * @access private
  4426  *
  4588  *
  4427  * @see WP_SITEURL
  4589  * @see WP_SITEURL
  4428  *
  4590  *
  4429  * @param string $url URL to set the WordPress site location.
  4591  * @param string $url URL to set the WordPress site location.
  4430  * @return string The WordPress Site URL.
  4592  * @return string The WordPress site URL.
  4431  */
  4593  */
  4432 function _config_wp_siteurl( $url = '' ) {
  4594 function _config_wp_siteurl( $url = '' ) {
  4433 	if ( defined( 'WP_SITEURL' ) ) {
  4595 	if ( defined( 'WP_SITEURL' ) ) {
  4434 		return untrailingslashit( WP_SITEURL );
  4596 		return untrailingslashit( WP_SITEURL );
  4435 	}
  4597 	}
  4978  * If you want to retrieve a particular field from all matching objects,
  5140  * If you want to retrieve a particular field from all matching objects,
  4979  * use wp_filter_object_list() instead.
  5141  * use wp_filter_object_list() instead.
  4980  *
  5142  *
  4981  * @since 3.1.0
  5143  * @since 3.1.0
  4982  * @since 4.7.0 Uses `WP_List_Util` class.
  5144  * @since 4.7.0 Uses `WP_List_Util` class.
       
  5145  * @since 5.9.0 Converted into a wrapper for `wp_filter_object_list()`.
  4983  *
  5146  *
  4984  * @param array  $list     An array of objects to filter.
  5147  * @param array  $list     An array of objects to filter.
  4985  * @param array  $args     Optional. An array of key => value arguments to match
  5148  * @param array  $args     Optional. An array of key => value arguments to match
  4986  *                         against each object. Default empty array.
  5149  *                         against each object. Default empty array.
  4987  * @param string $operator Optional. The logical operation to perform. 'AND' means
  5150  * @param string $operator Optional. The logical operation to perform. 'AND' means
  4989  *                         one element needs to match. 'NOT' means no elements may
  5152  *                         one element needs to match. 'NOT' means no elements may
  4990  *                         match. Default 'AND'.
  5153  *                         match. Default 'AND'.
  4991  * @return array Array of found values.
  5154  * @return array Array of found values.
  4992  */
  5155  */
  4993 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
  5156 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
  4994 	if ( ! is_array( $list ) ) {
  5157 	return wp_filter_object_list( $list, $args, $operator );
  4995 		return array();
  5158 }
  4996 	}
  5159 
  4997 
  5160 /**
  4998 	$util = new WP_List_Util( $list );
  5161  * Plucks a certain field out of each object or array in an array.
  4999 
       
  5000 	return $util->filter( $args, $operator );
       
  5001 }
       
  5002 
       
  5003 /**
       
  5004  * Pluck a certain field out of each object in a list.
       
  5005  *
  5162  *
  5006  * This has the same functionality and prototype of
  5163  * This has the same functionality and prototype of
  5007  * array_column() (PHP 5.5) but also supports objects.
  5164  * array_column() (PHP 5.5) but also supports objects.
  5008  *
  5165  *
  5009  * @since 3.1.0
  5166  * @since 3.1.0
  5017  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  5174  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  5018  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  5175  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  5019  *               `$list` will be preserved in the results.
  5176  *               `$list` will be preserved in the results.
  5020  */
  5177  */
  5021 function wp_list_pluck( $list, $field, $index_key = null ) {
  5178 function wp_list_pluck( $list, $field, $index_key = null ) {
       
  5179 	if ( ! is_array( $list ) ) {
       
  5180 		return array();
       
  5181 	}
       
  5182 
  5022 	$util = new WP_List_Util( $list );
  5183 	$util = new WP_List_Util( $list );
  5023 
  5184 
  5024 	return $util->pluck( $field, $index_key );
  5185 	return $util->pluck( $field, $index_key );
  5025 }
  5186 }
  5026 
  5187 
  5027 /**
  5188 /**
  5028  * Sorts a list of objects, based on one or more orderby arguments.
  5189  * Sorts an array of objects or arrays based on one or more orderby arguments.
  5029  *
  5190  *
  5030  * @since 4.7.0
  5191  * @since 4.7.0
  5031  *
  5192  *
  5032  * @param array        $list          An array of objects to sort.
  5193  * @param array        $list          An array of objects to sort.
  5033  * @param string|array $orderby       Optional. Either the field name to order by or an array
  5194  * @param string|array $orderby       Optional. Either the field name to order by or an array
  5078 
  5239 
  5079 /**
  5240 /**
  5080  * Append the Widgets menu to the themes main menu.
  5241  * Append the Widgets menu to the themes main menu.
  5081  *
  5242  *
  5082  * @since 2.2.0
  5243  * @since 2.2.0
       
  5244  * @since 5.9.3 Don't specify menu order when the active theme is a block theme.
  5083  *
  5245  *
  5084  * @global array $submenu
  5246  * @global array $submenu
  5085  */
  5247  */
  5086 function wp_widgets_add_menu() {
  5248 function wp_widgets_add_menu() {
  5087 	global $submenu;
  5249 	global $submenu;
  5088 
  5250 
  5089 	if ( ! current_theme_supports( 'widgets' ) ) {
  5251 	if ( ! current_theme_supports( 'widgets' ) ) {
  5090 		return;
  5252 		return;
  5091 	}
  5253 	}
  5092 
  5254 
  5093 	$submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' );
  5255 	$menu_name = __( 'Widgets' );
       
  5256 	if ( wp_is_block_theme() ) {
       
  5257 		$submenu['themes.php'][] = array( $menu_name, 'edit_theme_options', 'widgets.php' );
       
  5258 	} else {
       
  5259 		$submenu['themes.php'][7] = array( $menu_name, 'edit_theme_options', 'widgets.php' );
       
  5260 	}
       
  5261 
  5094 	ksort( $submenu['themes.php'], SORT_NUMERIC );
  5262 	ksort( $submenu['themes.php'], SORT_NUMERIC );
  5095 }
  5263 }
  5096 
  5264 
  5097 /**
  5265 /**
  5098  * Flush all output buffers for PHP 5.2.
  5266  * Flush all output buffers for PHP 5.2.
  5201 		if ( function_exists( '__' ) ) {
  5369 		if ( function_exists( '__' ) ) {
  5202 			if ( $replacement ) {
  5370 			if ( $replacement ) {
  5203 				trigger_error(
  5371 				trigger_error(
  5204 					sprintf(
  5372 					sprintf(
  5205 						/* translators: 1: PHP function name, 2: Version number, 3: Alternative function name. */
  5373 						/* translators: 1: PHP function name, 2: Version number, 3: Alternative function name. */
  5206 						__( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5374 						__( 'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5207 						$function,
  5375 						$function,
  5208 						$version,
  5376 						$version,
  5209 						$replacement
  5377 						$replacement
  5210 					),
  5378 					),
  5211 					E_USER_DEPRECATED
  5379 					E_USER_DEPRECATED
  5212 				);
  5380 				);
  5213 			} else {
  5381 			} else {
  5214 				trigger_error(
  5382 				trigger_error(
  5215 					sprintf(
  5383 					sprintf(
  5216 						/* translators: 1: PHP function name, 2: Version number. */
  5384 						/* translators: 1: PHP function name, 2: Version number. */
  5217 						__( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5385 						__( 'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5218 						$function,
  5386 						$function,
  5219 						$version
  5387 						$version
  5220 					),
  5388 					),
  5221 					E_USER_DEPRECATED
  5389 					E_USER_DEPRECATED
  5222 				);
  5390 				);
  5223 			}
  5391 			}
  5224 		} else {
  5392 		} else {
  5225 			if ( $replacement ) {
  5393 			if ( $replacement ) {
  5226 				trigger_error(
  5394 				trigger_error(
  5227 					sprintf(
  5395 					sprintf(
  5228 						'%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5396 						'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5229 						$function,
  5397 						$function,
  5230 						$version,
  5398 						$version,
  5231 						$replacement
  5399 						$replacement
  5232 					),
  5400 					),
  5233 					E_USER_DEPRECATED
  5401 					E_USER_DEPRECATED
  5234 				);
  5402 				);
  5235 			} else {
  5403 			} else {
  5236 				trigger_error(
  5404 				trigger_error(
  5237 					sprintf(
  5405 					sprintf(
  5238 						'%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5406 						'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5239 						$function,
  5407 						$function,
  5240 						$version
  5408 						$version
  5241 					),
  5409 					),
  5242 					E_USER_DEPRECATED
  5410 					E_USER_DEPRECATED
  5243 				);
  5411 				);
  5293 		if ( function_exists( '__' ) ) {
  5461 		if ( function_exists( '__' ) ) {
  5294 			if ( $parent_class ) {
  5462 			if ( $parent_class ) {
  5295 				trigger_error(
  5463 				trigger_error(
  5296 					sprintf(
  5464 					sprintf(
  5297 						/* translators: 1: PHP class name, 2: PHP parent class name, 3: Version number, 4: __construct() method. */
  5465 						/* translators: 1: PHP class name, 2: PHP parent class name, 3: Version number, 4: __construct() method. */
  5298 						__( 'The called constructor method for %1$s in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.' ),
  5466 						__( 'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.' ),
  5299 						$class,
  5467 						$class,
  5300 						$parent_class,
  5468 						$parent_class,
  5301 						$version,
  5469 						$version,
  5302 						'<code>__construct()</code>'
  5470 						'<code>__construct()</code>'
  5303 					),
  5471 					),
  5305 				);
  5473 				);
  5306 			} else {
  5474 			} else {
  5307 				trigger_error(
  5475 				trigger_error(
  5308 					sprintf(
  5476 					sprintf(
  5309 						/* translators: 1: PHP class name, 2: Version number, 3: __construct() method. */
  5477 						/* translators: 1: PHP class name, 2: Version number, 3: __construct() method. */
  5310 						__( 'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5478 						__( 'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5311 						$class,
  5479 						$class,
  5312 						$version,
  5480 						$version,
  5313 						'<code>__construct()</code>'
  5481 						'<code>__construct()</code>'
  5314 					),
  5482 					),
  5315 					E_USER_DEPRECATED
  5483 					E_USER_DEPRECATED
  5317 			}
  5485 			}
  5318 		} else {
  5486 		} else {
  5319 			if ( $parent_class ) {
  5487 			if ( $parent_class ) {
  5320 				trigger_error(
  5488 				trigger_error(
  5321 					sprintf(
  5489 					sprintf(
  5322 						'The called constructor method for %1$s in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
  5490 						'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
  5323 						$class,
  5491 						$class,
  5324 						$parent_class,
  5492 						$parent_class,
  5325 						$version,
  5493 						$version,
  5326 						'<code>__construct()</code>'
  5494 						'<code>__construct()</code>'
  5327 					),
  5495 					),
  5328 					E_USER_DEPRECATED
  5496 					E_USER_DEPRECATED
  5329 				);
  5497 				);
  5330 			} else {
  5498 			} else {
  5331 				trigger_error(
  5499 				trigger_error(
  5332 					sprintf(
  5500 					sprintf(
  5333 						'The called constructor method for %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5501 						'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5334 						$class,
  5502 						$class,
  5335 						$version,
  5503 						$version,
  5336 						'<code>__construct()</code>'
  5504 						'<code>__construct()</code>'
  5337 					),
  5505 					),
  5338 					E_USER_DEPRECATED
  5506 					E_USER_DEPRECATED
  5391 		if ( function_exists( '__' ) ) {
  5559 		if ( function_exists( '__' ) ) {
  5392 			if ( $replacement ) {
  5560 			if ( $replacement ) {
  5393 				trigger_error(
  5561 				trigger_error(
  5394 					sprintf(
  5562 					sprintf(
  5395 						/* translators: 1: PHP file name, 2: Version number, 3: Alternative file name. */
  5563 						/* translators: 1: PHP file name, 2: Version number, 3: Alternative file name. */
  5396 						__( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5564 						__( 'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5397 						$file,
  5565 						$file,
  5398 						$version,
  5566 						$version,
  5399 						$replacement
  5567 						$replacement
  5400 					) . $message,
  5568 					) . $message,
  5401 					E_USER_DEPRECATED
  5569 					E_USER_DEPRECATED
  5402 				);
  5570 				);
  5403 			} else {
  5571 			} else {
  5404 				trigger_error(
  5572 				trigger_error(
  5405 					sprintf(
  5573 					sprintf(
  5406 						/* translators: 1: PHP file name, 2: Version number. */
  5574 						/* translators: 1: PHP file name, 2: Version number. */
  5407 						__( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5575 						__( 'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5408 						$file,
  5576 						$file,
  5409 						$version
  5577 						$version
  5410 					) . $message,
  5578 					) . $message,
  5411 					E_USER_DEPRECATED
  5579 					E_USER_DEPRECATED
  5412 				);
  5580 				);
  5413 			}
  5581 			}
  5414 		} else {
  5582 		} else {
  5415 			if ( $replacement ) {
  5583 			if ( $replacement ) {
  5416 				trigger_error(
  5584 				trigger_error(
  5417 					sprintf(
  5585 					sprintf(
  5418 						'%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5586 						'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
  5419 						$file,
  5587 						$file,
  5420 						$version,
  5588 						$version,
  5421 						$replacement
  5589 						$replacement
  5422 					) . $message,
  5590 					) . $message,
  5423 					E_USER_DEPRECATED
  5591 					E_USER_DEPRECATED
  5424 				);
  5592 				);
  5425 			} else {
  5593 			} else {
  5426 				trigger_error(
  5594 				trigger_error(
  5427 					sprintf(
  5595 					sprintf(
  5428 						'%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5596 						'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5429 						$file,
  5597 						$file,
  5430 						$version
  5598 						$version
  5431 					) . $message,
  5599 					) . $message,
  5432 					E_USER_DEPRECATED
  5600 					E_USER_DEPRECATED
  5433 				);
  5601 				);
  5485 		if ( function_exists( '__' ) ) {
  5653 		if ( function_exists( '__' ) ) {
  5486 			if ( $message ) {
  5654 			if ( $message ) {
  5487 				trigger_error(
  5655 				trigger_error(
  5488 					sprintf(
  5656 					sprintf(
  5489 						/* translators: 1: PHP function name, 2: Version number, 3: Optional message regarding the change. */
  5657 						/* translators: 1: PHP function name, 2: Version number, 3: Optional message regarding the change. */
  5490 						__( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s' ),
  5658 						__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s' ),
  5491 						$function,
  5659 						$function,
  5492 						$version,
  5660 						$version,
  5493 						$message
  5661 						$message
  5494 					),
  5662 					),
  5495 					E_USER_DEPRECATED
  5663 					E_USER_DEPRECATED
  5496 				);
  5664 				);
  5497 			} else {
  5665 			} else {
  5498 				trigger_error(
  5666 				trigger_error(
  5499 					sprintf(
  5667 					sprintf(
  5500 						/* translators: 1: PHP function name, 2: Version number. */
  5668 						/* translators: 1: PHP function name, 2: Version number. */
  5501 						__( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5669 						__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5502 						$function,
  5670 						$function,
  5503 						$version
  5671 						$version
  5504 					),
  5672 					),
  5505 					E_USER_DEPRECATED
  5673 					E_USER_DEPRECATED
  5506 				);
  5674 				);
  5507 			}
  5675 			}
  5508 		} else {
  5676 		} else {
  5509 			if ( $message ) {
  5677 			if ( $message ) {
  5510 				trigger_error(
  5678 				trigger_error(
  5511 					sprintf(
  5679 					sprintf(
  5512 						'%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s',
  5680 						'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s',
  5513 						$function,
  5681 						$function,
  5514 						$version,
  5682 						$version,
  5515 						$message
  5683 						$message
  5516 					),
  5684 					),
  5517 					E_USER_DEPRECATED
  5685 					E_USER_DEPRECATED
  5518 				);
  5686 				);
  5519 			} else {
  5687 			} else {
  5520 				trigger_error(
  5688 				trigger_error(
  5521 					sprintf(
  5689 					sprintf(
  5522 						'%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5690 						'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.',
  5523 						$function,
  5691 						$function,
  5524 						$version
  5692 						$version
  5525 					),
  5693 					),
  5526 					E_USER_DEPRECATED
  5694 					E_USER_DEPRECATED
  5527 				);
  5695 				);
  5576 
  5744 
  5577 		if ( $replacement ) {
  5745 		if ( $replacement ) {
  5578 			trigger_error(
  5746 			trigger_error(
  5579 				sprintf(
  5747 				sprintf(
  5580 					/* translators: 1: WordPress hook name, 2: Version number, 3: Alternative hook name. */
  5748 					/* translators: 1: WordPress hook name, 2: Version number, 3: Alternative hook name. */
  5581 					__( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5749 					__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
  5582 					$hook,
  5750 					$hook,
  5583 					$version,
  5751 					$version,
  5584 					$replacement
  5752 					$replacement
  5585 				) . $message,
  5753 				) . $message,
  5586 				E_USER_DEPRECATED
  5754 				E_USER_DEPRECATED
  5587 			);
  5755 			);
  5588 		} else {
  5756 		} else {
  5589 			trigger_error(
  5757 			trigger_error(
  5590 				sprintf(
  5758 				sprintf(
  5591 					/* translators: 1: WordPress hook name, 2: Version number. */
  5759 					/* translators: 1: WordPress hook name, 2: Version number. */
  5592 					__( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5760 					__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
  5593 					$hook,
  5761 					$hook,
  5594 					$version
  5762 					$version
  5595 				) . $message,
  5763 				) . $message,
  5596 				E_USER_DEPRECATED
  5764 				E_USER_DEPRECATED
  5597 			);
  5765 			);
  5653 			);
  5821 			);
  5654 
  5822 
  5655 			trigger_error(
  5823 			trigger_error(
  5656 				sprintf(
  5824 				sprintf(
  5657 					/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: WordPress version number. */
  5825 					/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: WordPress version number. */
  5658 					__( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ),
  5826 					__( 'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s' ),
  5659 					$function,
  5827 					$function,
  5660 					$message,
  5828 					$message,
  5661 					$version
  5829 					$version
  5662 				),
  5830 				),
  5663 				E_USER_NOTICE
  5831 				E_USER_NOTICE
  5672 				'https://wordpress.org/support/article/debugging-in-wordpress/'
  5840 				'https://wordpress.org/support/article/debugging-in-wordpress/'
  5673 			);
  5841 			);
  5674 
  5842 
  5675 			trigger_error(
  5843 			trigger_error(
  5676 				sprintf(
  5844 				sprintf(
  5677 					'%1$s was called <strong>incorrectly</strong>. %2$s %3$s',
  5845 					'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s',
  5678 					$function,
  5846 					$function,
  5679 					$message,
  5847 					$message,
  5680 					$version
  5848 					$version
  5681 				),
  5849 				),
  5682 				E_USER_NOTICE
  5850 				E_USER_NOTICE
  5784  * @param string   $file          File path.
  5952  * @param string   $file          File path.
  5785  * @param string[] $allowed_files Optional. Array of allowed files.
  5953  * @param string[] $allowed_files Optional. Array of allowed files.
  5786  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
  5954  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
  5787  */
  5955  */
  5788 function validate_file( $file, $allowed_files = array() ) {
  5956 function validate_file( $file, $allowed_files = array() ) {
       
  5957 	if ( ! is_scalar( $file ) || '' === $file ) {
       
  5958 		return 0;
       
  5959 	}
       
  5960 
  5789 	// `../` on its own is not allowed:
  5961 	// `../` on its own is not allowed:
  5790 	if ( '../' === $file ) {
  5962 	if ( '../' === $file ) {
  5791 		return 1;
  5963 		return 1;
  5792 	}
  5964 	}
  5793 
  5965 
  5794 	// More than one occurence of `../` is not allowed:
  5966 	// More than one occurrence of `../` is not allowed:
  5795 	if ( preg_match_all( '#\.\./#', $file, $matches, PREG_SET_ORDER ) && ( count( $matches ) > 1 ) ) {
  5967 	if ( preg_match_all( '#\.\./#', $file, $matches, PREG_SET_ORDER ) && ( count( $matches ) > 1 ) ) {
  5796 		return 1;
  5968 		return 1;
  5797 	}
  5969 	}
  5798 
  5970 
  5799 	// `../` which does not occur at the end of the path is not allowed:
  5971 	// `../` which does not occur at the end of the path is not allowed:
  6455  * @param string $context         Optional. If specified adds filter hook {@see 'extra_$context_headers'}.
  6627  * @param string $context         Optional. If specified adds filter hook {@see 'extra_$context_headers'}.
  6456  *                                Default empty.
  6628  *                                Default empty.
  6457  * @return string[] Array of file header values keyed by header name.
  6629  * @return string[] Array of file header values keyed by header name.
  6458  */
  6630  */
  6459 function get_file_data( $file, $default_headers, $context = '' ) {
  6631 function get_file_data( $file, $default_headers, $context = '' ) {
  6460 	// We don't need to write to the file, so just open for reading.
  6632 	// Pull only the first 8 KB of the file in.
  6461 	$fp = fopen( $file, 'r' );
  6633 	$file_data = file_get_contents( $file, false, null, 0, 8 * KB_IN_BYTES );
  6462 
  6634 
  6463 	if ( $fp ) {
  6635 	if ( false === $file_data ) {
  6464 		// Pull only the first 8 KB of the file in.
       
  6465 		$file_data = fread( $fp, 8 * KB_IN_BYTES );
       
  6466 
       
  6467 		// PHP will close file handle, but we are good citizens.
       
  6468 		fclose( $fp );
       
  6469 	} else {
       
  6470 		$file_data = '';
  6636 		$file_data = '';
  6471 	}
  6637 	}
  6472 
  6638 
  6473 	// Make sure we catch CR-only line endings.
  6639 	// Make sure we catch CR-only line endings.
  6474 	$file_data = str_replace( "\r", "\n", $file_data );
  6640 	$file_data = str_replace( "\r", "\n", $file_data );
  6704 /**
  6870 /**
  6705  * Send a HTTP header to limit rendering of pages to same origin iframes.
  6871  * Send a HTTP header to limit rendering of pages to same origin iframes.
  6706  *
  6872  *
  6707  * @since 3.1.3
  6873  * @since 3.1.3
  6708  *
  6874  *
  6709  * @see https://developer.mozilla.org/en/the_x-frame-options_response_header
  6875  * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
  6710  */
  6876  */
  6711 function send_frame_options_header() {
  6877 function send_frame_options_header() {
  6712 	header( 'X-Frame-Options: SAMEORIGIN' );
  6878 	header( 'X-Frame-Options: SAMEORIGIN' );
  6713 }
  6879 }
  6714 
  6880 
  6750 
  6916 
  6751 	return $protocols;
  6917 	return $protocols;
  6752 }
  6918 }
  6753 
  6919 
  6754 /**
  6920 /**
  6755  * Return a comma-separated string of functions that have been called to get
  6921  * Returns a comma-separated string or array of functions that have been called to get
  6756  * to the current point in code.
  6922  * to the current point in code.
  6757  *
  6923  *
  6758  * @since 3.4.0
  6924  * @since 3.4.0
  6759  *
  6925  *
  6760  * @see https://core.trac.wordpress.org/ticket/19589
  6926  * @see https://core.trac.wordpress.org/ticket/19589
  6761  *
  6927  *
  6762  * @param string $ignore_class Optional. A class to ignore all function calls within - useful
  6928  * @param string $ignore_class Optional. A class to ignore all function calls within - useful
  6763  *                             when you want to just give info about the callee. Default null.
  6929  *                             when you want to just give info about the callee. Default null.
  6764  * @param int    $skip_frames  Optional. A number of stack frames to skip - useful for unwinding
  6930  * @param int    $skip_frames  Optional. A number of stack frames to skip - useful for unwinding
  6765  *                             back to the source of the issue. Default 0.
  6931  *                             back to the source of the issue. Default 0.
  6766  * @param bool   $pretty       Optional. Whether or not you want a comma separated string or raw
  6932  * @param bool   $pretty       Optional. Whether you want a comma separated string instead of
  6767  *                             array returned. Default true.
  6933  *                             the raw array returned. Default true.
  6768  * @return string|array Either a string containing a reversed comma separated trace or an array
  6934  * @return string|array Either a string containing a reversed comma separated trace or an array
  6769  *                      of individual calls.
  6935  *                      of individual calls.
  6770  */
  6936  */
  6771 function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
  6937 function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
  6772 	static $truncate_paths;
  6938 	static $truncate_paths;
  7561  * @param bool   $ipv6_fallback Optional. Whether to return the original IPv6 address if the needed functions
  7727  * @param bool   $ipv6_fallback Optional. Whether to return the original IPv6 address if the needed functions
  7562  *                              to anonymize it are not present. Default false, return `::` (unspecified address).
  7728  *                              to anonymize it are not present. Default false, return `::` (unspecified address).
  7563  * @return string  The anonymized IP address.
  7729  * @return string  The anonymized IP address.
  7564  */
  7730  */
  7565 function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
  7731 function wp_privacy_anonymize_ip( $ip_addr, $ipv6_fallback = false ) {
       
  7732 	if ( empty( $ip_addr ) ) {
       
  7733 		return '0.0.0.0';
       
  7734 	}
       
  7735 
  7566 	// Detect what kind of IP address this is.
  7736 	// Detect what kind of IP address this is.
  7567 	$ip_prefix = '';
  7737 	$ip_prefix = '';
  7568 	$is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
  7738 	$is_ipv6   = substr_count( $ip_addr, ':' ) > 1;
  7569 	$is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
  7739 	$is_ipv4   = ( 3 === substr_count( $ip_addr, '.' ) );
  7570 
  7740 
  8056  * @since MU (3.0.0)
  8226  * @since MU (3.0.0)
  8057  * @since 4.3.0 The `$exclude` parameter was added.
  8227  * @since 4.3.0 The `$exclude` parameter was added.
  8058  * @since 5.2.0 The `$max_execution_time` parameter was added.
  8228  * @since 5.2.0 The `$max_execution_time` parameter was added.
  8059  * @since 5.6.0 The `$directory_cache` parameter was added.
  8229  * @since 5.6.0 The `$directory_cache` parameter was added.
  8060  *
  8230  *
  8061  * @param string       $directory          Full path of a directory.
  8231  * @param string          $directory          Full path of a directory.
  8062  * @param string|array $exclude            Optional. Full path of a subdirectory to exclude from the total,
  8232  * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
  8063  *                                         or array of paths. Expected without trailing slash(es).
  8233  *                                            or array of paths. Expected without trailing slash(es).
  8064  * @param int          $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global
  8234  * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
  8065  *                                         and is measured from the moment WordPress started to load.
  8235  *                                            The timeout is global and is measured from the moment
  8066  * @param array        $directory_cache    Optional. Array of cached directory paths.
  8236  *                                            WordPress started to load.
       
  8237  * @param array           $directory_cache    Optional. Array of cached directory paths.
  8067  *
  8238  *
  8068  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  8239  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  8069  */
  8240  */
  8070 function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null, &$directory_cache = null ) {
  8241 function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null, &$directory_cache = null ) {
  8071 	$directory  = untrailingslashit( $directory );
  8242 	$directory  = untrailingslashit( $directory );
  8112 	 * Return the actual used space to short-circuit the recursive PHP file size calculation
  8283 	 * Return the actual used space to short-circuit the recursive PHP file size calculation
  8113 	 * and use something else, like a CDN API or native operating system tools for better performance.
  8284 	 * and use something else, like a CDN API or native operating system tools for better performance.
  8114 	 *
  8285 	 *
  8115 	 * @since 5.6.0
  8286 	 * @since 5.6.0
  8116 	 *
  8287 	 *
  8117 	 * @param int|false $space_used The amount of used space, in bytes. Default false.
  8288 	 * @param int|false            $space_used         The amount of used space, in bytes. Default false.
       
  8289 	 * @param string               $directory          Full path of a directory.
       
  8290 	 * @param string|string[]|null $exclude            Full path of a subdirectory to exclude from the total,
       
  8291 	 *                                                 or array of paths.
       
  8292 	 * @param int                  $max_execution_time Maximum time to run before giving up. In seconds.
       
  8293 	 * @param array                $directory_cache    Array of cached directory paths.
  8118 	 */
  8294 	 */
  8119 	$size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache );
  8295 	$size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache );
  8120 
  8296 
  8121 	if ( false === $size ) {
  8297 	if ( false === $size ) {
  8122 		$size = 0;
  8298 		$size = 0;
  8133 						if ( $handlesize > 0 ) {
  8309 						if ( $handlesize > 0 ) {
  8134 							$size += $handlesize;
  8310 							$size += $handlesize;
  8135 						}
  8311 						}
  8136 					}
  8312 					}
  8137 
  8313 
  8138 					if ( $max_execution_time > 0 && microtime( true ) - WP_START_TIMESTAMP > $max_execution_time ) {
  8314 					if ( $max_execution_time > 0 &&
       
  8315 						( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time
       
  8316 					) {
  8139 						// Time exceeded. Give up instead of risking a fatal timeout.
  8317 						// Time exceeded. Give up instead of risking a fatal timeout.
  8140 						$size = null;
  8318 						$size = null;
  8141 						break;
  8319 						break;
  8142 					}
  8320 					}
  8143 				}
  8321 				}
  8144 			}
  8322 			}
  8145 			closedir( $handle );
  8323 			closedir( $handle );
  8146 		}
  8324 		}
  8147 	}
  8325 	}
  8148 
  8326 
       
  8327 	if ( ! is_array( $directory_cache ) ) {
       
  8328 		$directory_cache = array();
       
  8329 	}
       
  8330 
  8149 	$directory_cache[ $directory ] = $size;
  8331 	$directory_cache[ $directory ] = $size;
  8150 
  8332 
  8151 	// Only write the transient on the top level call and not on recursive calls.
  8333 	// Only write the transient on the top level call and not on recursive calls.
  8152 	if ( $save_cache ) {
  8334 	if ( $save_cache ) {
  8153 		set_transient( 'dirsize_cache', $directory_cache );
  8335 		set_transient( 'dirsize_cache', $directory_cache );
  8160  * Cleans directory size cache used by recurse_dirsize().
  8342  * Cleans directory size cache used by recurse_dirsize().
  8161  *
  8343  *
  8162  * Removes the current directory and all parent directories from the `dirsize_cache` transient.
  8344  * Removes the current directory and all parent directories from the `dirsize_cache` transient.
  8163  *
  8345  *
  8164  * @since 5.6.0
  8346  * @since 5.6.0
       
  8347  * @since 5.9.0 Added input validation with a notice for invalid input.
  8165  *
  8348  *
  8166  * @param string $path Full path of a directory or file.
  8349  * @param string $path Full path of a directory or file.
  8167  */
  8350  */
  8168 function clean_dirsize_cache( $path ) {
  8351 function clean_dirsize_cache( $path ) {
       
  8352 	if ( ! is_string( $path ) || empty( $path ) ) {
       
  8353 		trigger_error(
       
  8354 			sprintf(
       
  8355 				/* translators: 1: Function name, 2: A variable type, like "boolean" or "integer". */
       
  8356 				__( '%1$s only accepts a non-empty path string, received %2$s.' ),
       
  8357 				'<code>clean_dirsize_cache()</code>',
       
  8358 				'<code>' . gettype( $path ) . '</code>'
       
  8359 			)
       
  8360 		);
       
  8361 		return;
       
  8362 	}
       
  8363 
  8169 	$directory_cache = get_transient( 'dirsize_cache' );
  8364 	$directory_cache = get_transient( 'dirsize_cache' );
  8170 
  8365 
  8171 	if ( empty( $directory_cache ) ) {
  8366 	if ( empty( $directory_cache ) ) {
  8172 		return;
  8367 		return;
  8173 	}
  8368 	}
  8174 
  8369 
  8175 	$path = untrailingslashit( $path );
  8370 	if (
       
  8371 		strpos( $path, '/' ) === false &&
       
  8372 		strpos( $path, '\\' ) === false
       
  8373 	) {
       
  8374 		unset( $directory_cache[ $path ] );
       
  8375 		set_transient( 'dirsize_cache', $directory_cache );
       
  8376 		return;
       
  8377 	}
       
  8378 
       
  8379 	$last_path = null;
       
  8380 	$path      = untrailingslashit( $path );
  8176 	unset( $directory_cache[ $path ] );
  8381 	unset( $directory_cache[ $path ] );
  8177 
  8382 
  8178 	while ( DIRECTORY_SEPARATOR !== $path && '.' !== $path && '..' !== $path ) {
  8383 	while (
  8179 		$path = dirname( $path );
  8384 		$last_path !== $path &&
       
  8385 		DIRECTORY_SEPARATOR !== $path &&
       
  8386 		'.' !== $path &&
       
  8387 		'..' !== $path
       
  8388 	) {
       
  8389 		$last_path = $path;
       
  8390 		$path      = dirname( $path );
  8180 		unset( $directory_cache[ $path ] );
  8391 		unset( $directory_cache[ $path ] );
  8181 	}
  8392 	}
  8182 
  8393 
  8183 	set_transient( 'dirsize_cache', $directory_cache );
  8394 	set_transient( 'dirsize_cache', $directory_cache );
  8184 }
  8395 }
  8185 
  8396 
  8186 /**
  8397 /**
  8187  * Checks compatibility with the current WordPress version.
  8398  * Checks compatibility with the current WordPress version.
  8188  *
  8399  *
  8189  * @since 5.2.0
  8400  * @since 5.2.0
       
  8401  *
       
  8402  * @global string $wp_version The WordPress version string.
  8190  *
  8403  *
  8191  * @param string $required Minimum required WordPress version.
  8404  * @param string $required Minimum required WordPress version.
  8192  * @return bool True if required version is compatible or empty, false if not.
  8405  * @return bool True if required version is compatible or empty, false if not.
  8193  */
  8406  */
  8194 function is_wp_version_compatible( $required ) {
  8407 function is_wp_version_compatible( $required ) {
  8195 	return empty( $required ) || version_compare( get_bloginfo( 'version' ), $required, '>=' );
  8408 	global $wp_version;
       
  8409 
       
  8410 	// Strip off any -alpha, -RC, -beta, -src suffixes.
       
  8411 	list( $version ) = explode( '-', $wp_version );
       
  8412 
       
  8413 	return empty( $required ) || version_compare( $version, $required, '>=' );
  8196 }
  8414 }
  8197 
  8415 
  8198 /**
  8416 /**
  8199  * Checks compatibility with the current PHP version.
  8417  * Checks compatibility with the current PHP version.
  8200  *
  8418  *
  8206 function is_php_version_compatible( $required ) {
  8424 function is_php_version_compatible( $required ) {
  8207 	return empty( $required ) || version_compare( phpversion(), $required, '>=' );
  8425 	return empty( $required ) || version_compare( phpversion(), $required, '>=' );
  8208 }
  8426 }
  8209 
  8427 
  8210 /**
  8428 /**
  8211  * Check if two numbers are nearly the same.
  8429  * Checks if two numbers are nearly the same.
  8212  *
  8430  *
  8213  * This is similar to using `round()` but the precision is more fine-grained.
  8431  * This is similar to using `round()` but the precision is more fine-grained.
  8214  *
  8432  *
  8215  * @since 5.3.0
  8433  * @since 5.3.0
  8216  *
  8434  *
  8217  * @param int|float $expected  The expected value.
  8435  * @param int|float $expected  The expected value.
  8218  * @param int|float $actual    The actual number.
  8436  * @param int|float $actual    The actual number.
  8219  * @param int|float $precision The allowed variation.
  8437  * @param int|float $precision The allowed variation.
  8220  * @return bool Whether the numbers match whithin the specified precision.
  8438  * @return bool Whether the numbers match within the specified precision.
  8221  */
  8439  */
  8222 function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
  8440 function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
  8223 	return abs( (float) $expected - (float) $actual ) <= $precision;
  8441 	return abs( (float) $expected - (float) $actual ) <= $precision;
  8224 }
  8442 }
       
  8443 
       
  8444 /**
       
  8445  * Sorts the keys of an array alphabetically.
       
  8446  * The array is passed by reference so it doesn't get returned
       
  8447  * which mimics the behaviour of ksort.
       
  8448  *
       
  8449  * @since 6.0.0
       
  8450  *
       
  8451  * @param array $array The array to sort, passed by reference.
       
  8452  */
       
  8453 function wp_recursive_ksort( &$array ) {
       
  8454 	foreach ( $array as &$value ) {
       
  8455 		if ( is_array( $value ) ) {
       
  8456 			wp_recursive_ksort( $value );
       
  8457 		}
       
  8458 	}
       
  8459 	ksort( $array );
       
  8460 }