wp/wp-includes/functions.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
   465 		/* translators: Unit symbol for byte. */
   465 		/* translators: Unit symbol for byte. */
   466 		return number_format_i18n( 0, $decimals ) . ' ' . _x( 'B', 'unit symbol' );
   466 		return number_format_i18n( 0, $decimals ) . ' ' . _x( 'B', 'unit symbol' );
   467 	}
   467 	}
   468 
   468 
   469 	foreach ( $quant as $unit => $mag ) {
   469 	foreach ( $quant as $unit => $mag ) {
   470 		if ( doubleval( $bytes ) >= $mag ) {
   470 		if ( (float) $bytes >= $mag ) {
   471 			return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
   471 			return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
   472 		}
   472 		}
   473 	}
   473 	}
   474 
   474 
   475 	return false;
   475 	return false;
   828  * pingbacks and trackbacks.
   828  * pingbacks and trackbacks.
   829  *
   829  *
   830  * @since 1.5.0
   830  * @since 1.5.0
   831  * @since 5.3.0 The `$content` parameter was made optional, and the `$post` parameter was
   831  * @since 5.3.0 The `$content` parameter was made optional, and the `$post` parameter was
   832  *              updated to accept a post ID or a WP_Post object.
   832  *              updated to accept a post ID or a WP_Post object.
       
   833  * @since 5.6.0 The `$content` parameter is no longer optional, but passing `null` to skip it
       
   834  *              is still supported.
   833  *
   835  *
   834  * @global wpdb $wpdb WordPress database abstraction object.
   836  * @global wpdb $wpdb WordPress database abstraction object.
   835  *
   837  *
   836  * @param string      $content Post content. If `null`, the `post_content` field from `$post` is used.
   838  * @param string|null $content Post content. If `null`, the `post_content` field from `$post` is used.
   837  * @param int|WP_Post $post    Post ID or post object.
   839  * @param int|WP_Post $post    Post ID or post object.
   838  * @return null|bool Returns false if post is not found.
   840  * @return void|false Void on success, false if the post is not found.
   839  */
   841  */
   840 function do_enclose( $content = null, $post ) {
   842 function do_enclose( $content, $post ) {
   841 	global $wpdb;
   843 	global $wpdb;
   842 
   844 
   843 	// @todo Tidy this code and make the debug code optional.
   845 	// @todo Tidy this code and make the debug code optional.
   844 	include_once ABSPATH . WPINC . '/class-IXR.php';
   846 	include_once ABSPATH . WPINC . '/class-IXR.php';
   845 
   847 
   895 	 * @param int      $post_ID    Post ID.
   897 	 * @param int      $post_ID    Post ID.
   896 	 */
   898 	 */
   897 	$post_links = apply_filters( 'enclosure_links', $post_links, $post->ID );
   899 	$post_links = apply_filters( 'enclosure_links', $post_links, $post->ID );
   898 
   900 
   899 	foreach ( (array) $post_links as $url ) {
   901 	foreach ( (array) $post_links as $url ) {
       
   902 		$url = strip_fragment_from_url( $url );
       
   903 
   900 		if ( '' !== $url && ! $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
   904 		if ( '' !== $url && ! $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE %s", $post->ID, $wpdb->esc_like( $url ) . '%' ) ) ) {
   901 
   905 
   902 			$headers = wp_get_http_headers( $url );
   906 			$headers = wp_get_http_headers( $url );
   903 			if ( $headers ) {
   907 			if ( $headers ) {
   904 				$len           = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
   908 				$len           = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
   932  *
   936  *
   933  * @since 1.5.1
   937  * @since 1.5.1
   934  *
   938  *
   935  * @param string $url        URL to retrieve HTTP headers from.
   939  * @param string $url        URL to retrieve HTTP headers from.
   936  * @param bool   $deprecated Not Used.
   940  * @param bool   $deprecated Not Used.
   937  * @return bool|string False on failure, headers on success.
   941  * @return string|false Headers on success, false on failure.
   938  */
   942  */
   939 function wp_get_http_headers( $url, $deprecated = false ) {
   943 function wp_get_http_headers( $url, $deprecated = false ) {
   940 	if ( ! empty( $deprecated ) ) {
   944 	if ( ! empty( $deprecated ) ) {
   941 		_deprecated_argument( __FUNCTION__, '2.7.0' );
   945 		_deprecated_argument( __FUNCTION__, '2.7.0' );
   942 	}
   946 	}
  1153 /**
  1157 /**
  1154  * Removes an item or items from a query string.
  1158  * Removes an item or items from a query string.
  1155  *
  1159  *
  1156  * @since 1.5.0
  1160  * @since 1.5.0
  1157  *
  1161  *
  1158  * @param string|array $key   Query key or keys to remove.
  1162  * @param string|string[] $key   Query key or keys to remove.
  1159  * @param bool|string  $query Optional. When false uses the current URL. Default false.
  1163  * @param false|string    $query Optional. When false uses the current URL. Default false.
  1160  * @return string New URL query string.
  1164  * @return string New URL query string.
  1161  */
  1165  */
  1162 function remove_query_arg( $key, $query = false ) {
  1166 function remove_query_arg( $key, $query = false ) {
  1163 	if ( is_array( $key ) ) { // Removing multiple keys.
  1167 	if ( is_array( $key ) ) { // Removing multiple keys.
  1164 		foreach ( $key as $k ) {
  1168 		foreach ( $key as $k ) {
  1172 /**
  1176 /**
  1173  * Returns an array of single-use query variable names that can be removed from a URL.
  1177  * Returns an array of single-use query variable names that can be removed from a URL.
  1174  *
  1178  *
  1175  * @since 4.4.0
  1179  * @since 4.4.0
  1176  *
  1180  *
  1177  * @return string[] An array of parameters to remove from the URL.
  1181  * @return string[] An array of query variable names to remove from the URL.
  1178  */
  1182  */
  1179 function wp_removable_query_args() {
  1183 function wp_removable_query_args() {
  1180 	$removable_query_args = array(
  1184 	$removable_query_args = array(
  1181 		'activate',
  1185 		'activate',
  1182 		'activated',
  1186 		'activated',
  1183 		'admin_email_remind_later',
  1187 		'admin_email_remind_later',
  1184 		'approved',
  1188 		'approved',
       
  1189 		'core-major-auto-updates-saved',
  1185 		'deactivate',
  1190 		'deactivate',
  1186 		'delete_count',
  1191 		'delete_count',
  1187 		'deleted',
  1192 		'deleted',
  1188 		'disabled',
  1193 		'disabled',
  1189 		'doing_wp_cron',
  1194 		'doing_wp_cron',
  1190 		'enabled',
  1195 		'enabled',
  1191 		'error',
  1196 		'error',
  1192 		'hotkeys_highlight_first',
  1197 		'hotkeys_highlight_first',
  1193 		'hotkeys_highlight_last',
  1198 		'hotkeys_highlight_last',
       
  1199 		'ids',
  1194 		'locked',
  1200 		'locked',
  1195 		'message',
  1201 		'message',
  1196 		'same',
  1202 		'same',
  1197 		'saved',
  1203 		'saved',
  1198 		'settings-updated',
  1204 		'settings-updated',
  1205 		'updated',
  1211 		'updated',
  1206 		'wp-post-new-reload',
  1212 		'wp-post-new-reload',
  1207 	);
  1213 	);
  1208 
  1214 
  1209 	/**
  1215 	/**
  1210 	 * Filters the list of query variables to remove.
  1216 	 * Filters the list of query variable names to remove.
  1211 	 *
  1217 	 *
  1212 	 * @since 4.2.0
  1218 	 * @since 4.2.0
  1213 	 *
  1219 	 *
  1214 	 * @param string[] $removable_query_args An array of query variables to remove from a URL.
  1220 	 * @param string[] $removable_query_args An array of query variable names to remove from a URL.
  1215 	 */
  1221 	 */
  1216 	return apply_filters( 'removable_query_args', $removable_query_args );
  1222 	return apply_filters( 'removable_query_args', $removable_query_args );
  1217 }
  1223 }
  1218 
  1224 
  1219 /**
  1225 /**
  1560 
  1566 
  1561 	/**
  1567 	/**
  1562 	 * Fires once the given feed is loaded.
  1568 	 * Fires once the given feed is loaded.
  1563 	 *
  1569 	 *
  1564 	 * The dynamic portion of the hook name, `$feed`, refers to the feed template name.
  1570 	 * The dynamic portion of the hook name, `$feed`, refers to the feed template name.
  1565 	 * Possible values include: 'rdf', 'rss', 'rss2', and 'atom'.
  1571 	 *
       
  1572 	 * Possible hook names include:
       
  1573 	 *
       
  1574 	 *  - `do_feed_atom`
       
  1575 	 *  - `do_feed_rdf`
       
  1576 	 *  - `do_feed_rss`
       
  1577 	 *  - `do_feed_rss2`
  1566 	 *
  1578 	 *
  1567 	 * @since 2.1.0
  1579 	 * @since 2.1.0
  1568 	 * @since 4.4.0 The `$feed` parameter was added.
  1580 	 * @since 4.4.0 The `$feed` parameter was added.
  1569 	 *
  1581 	 *
  1570 	 * @param bool   $is_comment_feed Whether the feed is a comment feed.
  1582 	 * @param bool   $is_comment_feed Whether the feed is a comment feed.
  1632 /**
  1644 /**
  1633  * Displays the default robots.txt file content.
  1645  * Displays the default robots.txt file content.
  1634  *
  1646  *
  1635  * @since 2.1.0
  1647  * @since 2.1.0
  1636  * @since 5.3.0 Remove the "Disallow: /" output if search engine visiblity is
  1648  * @since 5.3.0 Remove the "Disallow: /" output if search engine visiblity is
  1637  *              discouraged in favor of robots meta HTML tag in wp_no_robots().
  1649  *              discouraged in favor of robots meta HTML tag via wp_robots_no_robots()
       
  1650  *              filter callback.
  1638  */
  1651  */
  1639 function do_robots() {
  1652 function do_robots() {
  1640 	header( 'Content-Type: text/plain; charset=utf-8' );
  1653 	header( 'Content-Type: text/plain; charset=utf-8' );
  1641 
  1654 
  1642 	/**
  1655 	/**
  1743 	 * If one or more exist, suggest table repair since we got here because the
  1756 	 * If one or more exist, suggest table repair since we got here because the
  1744 	 * options table could not be accessed.
  1757 	 * options table could not be accessed.
  1745 	 */
  1758 	 */
  1746 	$wp_tables = $wpdb->tables();
  1759 	$wp_tables = $wpdb->tables();
  1747 	foreach ( $wp_tables as $table ) {
  1760 	foreach ( $wp_tables as $table ) {
  1748 		// The existence of custom user tables shouldn't suggest an insane state or prevent a clean installation.
  1761 		// The existence of custom user tables shouldn't suggest an unwise state or prevent a clean installation.
  1749 		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table ) {
  1762 		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table ) {
  1750 			continue;
  1763 			continue;
  1751 		}
  1764 		}
  1752 		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table ) {
  1765 		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table ) {
  1753 			continue;
  1766 			continue;
  1754 		}
  1767 		}
  1755 
  1768 
  1756 		if ( ! $wpdb->get_results( "DESCRIBE $table;" ) ) {
  1769 		$described_table = $wpdb->get_results( "DESCRIBE $table;" );
       
  1770 		if (
       
  1771 			( ! $described_table && empty( $wpdb->last_error ) ) ||
       
  1772 			( is_array( $described_table ) && 0 === count( $described_table ) )
       
  1773 		) {
  1757 			continue;
  1774 			continue;
  1758 		}
  1775 		}
  1759 
  1776 
  1760 		// One or more tables exist. We are insane.
  1777 		// One or more tables exist. This is not good.
  1761 
  1778 
  1762 		wp_load_translations_early();
  1779 		wp_load_translations_early();
  1763 
  1780 
  1764 		// Die with a DB error.
  1781 		// Die with a DB error.
  1765 		$wpdb->error = sprintf(
  1782 		$wpdb->error = sprintf(
  2466 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
  2483 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
  2467 	// Sanitize the file name before we begin processing.
  2484 	// Sanitize the file name before we begin processing.
  2468 	$filename = sanitize_file_name( $filename );
  2485 	$filename = sanitize_file_name( $filename );
  2469 	$ext2     = null;
  2486 	$ext2     = null;
  2470 
  2487 
       
  2488 	// Initialize vars used in the wp_unique_filename filter.
       
  2489 	$number        = '';
       
  2490 	$alt_filenames = array();
       
  2491 
  2471 	// Separate the filename into a name and extension.
  2492 	// Separate the filename into a name and extension.
  2472 	$ext  = pathinfo( $filename, PATHINFO_EXTENSION );
  2493 	$ext  = pathinfo( $filename, PATHINFO_EXTENSION );
  2473 	$name = pathinfo( $filename, PATHINFO_BASENAME );
  2494 	$name = pathinfo( $filename, PATHINFO_BASENAME );
  2474 
  2495 
  2475 	if ( $ext ) {
  2496 	if ( $ext ) {
  2486 	 * Use callback if supplied.
  2507 	 * Use callback if supplied.
  2487 	 */
  2508 	 */
  2488 	if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
  2509 	if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
  2489 		$filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
  2510 		$filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
  2490 	} else {
  2511 	} else {
  2491 		$number = '';
  2512 		$fname = pathinfo( $filename, PATHINFO_FILENAME );
  2492 		$fname  = pathinfo( $filename, PATHINFO_FILENAME );
       
  2493 
  2513 
  2494 		// Always append a number to file names that can potentially match image sub-size file names.
  2514 		// Always append a number to file names that can potentially match image sub-size file names.
  2495 		if ( $fname && preg_match( '/-(?:\d+x\d+|scaled|rotated)$/', $fname ) ) {
  2515 		if ( $fname && preg_match( '/-(?:\d+x\d+|scaled|rotated)$/', $fname ) ) {
  2496 			$number = 1;
  2516 			$number = 1;
  2497 
  2517 
  2498 			// At this point the file name may not be unique. This is tested below and the $number is incremented.
  2518 			// At this point the file name may not be unique. This is tested below and the $number is incremented.
  2499 			$filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename );
  2519 			$filename = str_replace( "{$fname}{$ext}", "{$fname}-{$number}{$ext}", $filename );
  2500 		}
  2520 		}
  2501 
  2521 
  2502 		// Change '.ext' to lower case.
  2522 		// Get the mime type. Uploaded files were already checked with wp_check_filetype_and_ext()
  2503 		if ( $ext && strtolower( $ext ) != $ext ) {
  2523 		// in _wp_handle_upload(). Using wp_check_filetype() would be sufficient here.
  2504 			$ext2      = strtolower( $ext );
  2524 		$file_type = wp_check_filetype( $filename );
  2505 			$filename2 = preg_replace( '|' . preg_quote( $ext ) . '$|', $ext2, $filename );
  2525 		$mime_type = $file_type['type'];
  2506 
  2526 
  2507 			// Check for both lower and upper case extension or image sub-sizes may be overwritten.
  2527 		$is_image    = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) );
  2508 			while ( file_exists( $dir . "/{$filename}" ) || file_exists( $dir . "/{$filename2}" ) ) {
  2528 		$upload_dir  = wp_get_upload_dir();
  2509 				$new_number = (int) $number + 1;
  2529 		$lc_filename = null;
  2510 				$filename   = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename );
  2530 
  2511 				$filename2  = str_replace( array( "-{$number}{$ext2}", "{$number}{$ext2}" ), "-{$new_number}{$ext2}", $filename2 );
  2531 		$lc_ext = strtolower( $ext );
  2512 				$number     = $new_number;
  2532 		$_dir   = trailingslashit( $dir );
       
  2533 
       
  2534 		// If the extension is uppercase add an alternate file name with lowercase extension. Both need to be tested
       
  2535 		// for uniqueness as the extension will be changed to lowercase for better compatibility with different filesystems.
       
  2536 		// Fixes an inconsistency in WP < 2.9 where uppercase extensions were allowed but image sub-sizes were created with
       
  2537 		// lowercase extensions.
       
  2538 		if ( $ext && $lc_ext !== $ext ) {
       
  2539 			$lc_filename = preg_replace( '|' . preg_quote( $ext ) . '$|', $lc_ext, $filename );
       
  2540 		}
       
  2541 
       
  2542 		// Increment the number added to the file name if there are any files in $dir whose names match one of the
       
  2543 		// possible name variations.
       
  2544 		while ( file_exists( $_dir . $filename ) || ( $lc_filename && file_exists( $_dir . $lc_filename ) ) ) {
       
  2545 			$new_number = (int) $number + 1;
       
  2546 
       
  2547 			if ( $lc_filename ) {
       
  2548 				$lc_filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $lc_filename );
  2513 			}
  2549 			}
  2514 
  2550 
  2515 			$filename = $filename2;
  2551 			if ( '' === "{$number}{$ext}" ) {
  2516 		} else {
  2552 				$filename = "{$filename}-{$new_number}";
  2517 			while ( file_exists( $dir . "/{$filename}" ) ) {
  2553 			} else {
  2518 				$new_number = (int) $number + 1;
  2554 				$filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename );
  2519 
       
  2520 				if ( '' === "{$number}{$ext}" ) {
       
  2521 					$filename = "{$filename}-{$new_number}";
       
  2522 				} else {
       
  2523 					$filename = str_replace( array( "-{$number}{$ext}", "{$number}{$ext}" ), "-{$new_number}{$ext}", $filename );
       
  2524 				}
       
  2525 
       
  2526 				$number = $new_number;
       
  2527 			}
  2555 			}
       
  2556 
       
  2557 			$number = $new_number;
       
  2558 		}
       
  2559 
       
  2560 		// Change the extension to lowercase if needed.
       
  2561 		if ( $lc_filename ) {
       
  2562 			$filename = $lc_filename;
  2528 		}
  2563 		}
  2529 
  2564 
  2530 		// Prevent collisions with existing file names that contain dimension-like strings
  2565 		// Prevent collisions with existing file names that contain dimension-like strings
  2531 		// (whether they are subsizes or originals uploaded prior to #42437).
  2566 		// (whether they are subsizes or originals uploaded prior to #42437).
  2532 		$upload_dir = wp_get_upload_dir();
  2567 
       
  2568 		$files = array();
       
  2569 		$count = 10000;
  2533 
  2570 
  2534 		// The (resized) image files would have name and extension, and will be in the uploads dir.
  2571 		// The (resized) image files would have name and extension, and will be in the uploads dir.
  2535 		if ( $name && $ext && @is_dir( $dir ) && false !== strpos( $dir, $upload_dir['basedir'] ) ) {
  2572 		if ( $name && $ext && @is_dir( $dir ) && false !== strpos( $dir, $upload_dir['basedir'] ) ) {
  2536 			/**
  2573 			/**
  2537 			 * Filters the file list used for calculating a unique filename for a newly added file.
  2574 			 * Filters the file list used for calculating a unique filename for a newly added file.
  2557 				// Remove "dot" dirs.
  2594 				// Remove "dot" dirs.
  2558 				$files = array_diff( $files, array( '.', '..' ) );
  2595 				$files = array_diff( $files, array( '.', '..' ) );
  2559 			}
  2596 			}
  2560 
  2597 
  2561 			if ( ! empty( $files ) ) {
  2598 			if ( ! empty( $files ) ) {
  2562 				// The extension case may have changed above.
  2599 				$count = count( $files );
  2563 				$new_ext = ! empty( $ext2 ) ? $ext2 : $ext;
       
  2564 
  2600 
  2565 				// Ensure this never goes into infinite loop
  2601 				// Ensure this never goes into infinite loop
  2566 				// as it uses pathinfo() and regex in the check, but string replacement for the changes.
  2602 				// as it uses pathinfo() and regex in the check, but string replacement for the changes.
  2567 				$count = count( $files );
  2603 				$i = 0;
  2568 				$i     = 0;
       
  2569 
  2604 
  2570 				while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) {
  2605 				while ( $i <= $count && _wp_check_existing_file_names( $filename, $files ) ) {
  2571 					$new_number = (int) $number + 1;
  2606 					$new_number = (int) $number + 1;
  2572 					$filename   = str_replace( array( "-{$number}{$new_ext}", "{$number}{$new_ext}" ), "-{$new_number}{$new_ext}", $filename );
  2607 
  2573 					$number     = $new_number;
  2608 					// 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 );
       
  2610 
       
  2611 					$number = $new_number;
  2574 					$i++;
  2612 					$i++;
  2575 				}
  2613 				}
  2576 			}
  2614 			}
  2577 		}
  2615 		}
       
  2616 
       
  2617 		// Check if an image will be converted after uploading or some existing images sub-sizes file names may conflict
       
  2618 		// when regenerated. If yes, ensure the new file name will be unique and will produce unique sub-sizes.
       
  2619 		if ( $is_image ) {
       
  2620 			$output_formats = apply_filters( 'image_editor_output_format', array(), $_dir . $filename, $mime_type );
       
  2621 			$alt_types      = array();
       
  2622 
       
  2623 			if ( ! empty( $output_formats[ $mime_type ] ) ) {
       
  2624 				// The image will be converted to this format/mime type.
       
  2625 				$alt_mime_type = $output_formats[ $mime_type ];
       
  2626 
       
  2627 				// Other types of images whose names may conflict if their sub-sizes are regenerated.
       
  2628 				$alt_types   = array_keys( array_intersect( $output_formats, array( $mime_type, $alt_mime_type ) ) );
       
  2629 				$alt_types[] = $alt_mime_type;
       
  2630 			} elseif ( ! empty( $output_formats ) ) {
       
  2631 				$alt_types = array_keys( array_intersect( $output_formats, array( $mime_type ) ) );
       
  2632 			}
       
  2633 
       
  2634 			// Remove duplicates and the original mime type. It will be added later if needed.
       
  2635 			$alt_types = array_unique( array_diff( $alt_types, array( $mime_type ) ) );
       
  2636 
       
  2637 			foreach ( $alt_types as $alt_type ) {
       
  2638 				$alt_ext = wp_get_default_extension_for_mime_type( $alt_type );
       
  2639 
       
  2640 				if ( ! $alt_ext ) {
       
  2641 					continue;
       
  2642 				}
       
  2643 
       
  2644 				$alt_ext      = ".{$alt_ext}";
       
  2645 				$alt_filename = preg_replace( '|' . preg_quote( $lc_ext ) . '$|', $alt_ext, $filename );
       
  2646 
       
  2647 				$alt_filenames[ $alt_ext ] = $alt_filename;
       
  2648 			}
       
  2649 
       
  2650 			if ( ! empty( $alt_filenames ) ) {
       
  2651 				// Add the original filename. It needs to be checked again together with the alternate filenames
       
  2652 				// when $number is incremented.
       
  2653 				$alt_filenames[ $lc_ext ] = $filename;
       
  2654 
       
  2655 				// Ensure no infinite loop.
       
  2656 				$i = 0;
       
  2657 
       
  2658 				while ( $i <= $count && _wp_check_alternate_file_names( $alt_filenames, $_dir, $files ) ) {
       
  2659 					$new_number = (int) $number + 1;
       
  2660 
       
  2661 					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 );
       
  2663 					}
       
  2664 
       
  2665 					// Also update the $number in (the output) $filename.
       
  2666 					// If the extension was uppercase it was already replaced with the lowercase version.
       
  2667 					$filename = str_replace( array( "-{$number}{$lc_ext}", "{$number}{$lc_ext}" ), "-{$new_number}{$lc_ext}", $filename );
       
  2668 
       
  2669 					$number = $new_number;
       
  2670 					$i++;
       
  2671 				}
       
  2672 			}
       
  2673 		}
  2578 	}
  2674 	}
  2579 
  2675 
  2580 	/**
  2676 	/**
  2581 	 * Filters the result when generating a unique file name.
  2677 	 * Filters the result when generating a unique file name.
  2582 	 *
  2678 	 *
  2583 	 * @since 4.5.0
  2679 	 * @since 4.5.0
       
  2680 	 * @since 5.8.1 The `$alt_filenames` and `$number` parameters were added.
  2584 	 *
  2681 	 *
  2585 	 * @param string        $filename                 Unique file name.
  2682 	 * @param string        $filename                 Unique file name.
  2586 	 * @param string        $ext                      File extension, eg. ".png".
  2683 	 * @param string        $ext                      File extension, eg. ".png".
  2587 	 * @param string        $dir                      Directory path.
  2684 	 * @param string        $dir                      Directory path.
  2588 	 * @param callable|null $unique_filename_callback Callback function that generates the unique file name.
  2685 	 * @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.
       
  2687 	 * @param int|string    $number                   The highest number that was used to make the file name unique
       
  2688 	 *                                                or an empty string if unused.
  2589 	 */
  2689 	 */
  2590 	return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback );
  2690 	return apply_filters( 'wp_unique_filename', $filename, $ext, $dir, $unique_filename_callback, $alt_filenames, $number );
       
  2691 }
       
  2692 
       
  2693 /**
       
  2694  * Helper function to test if each of an array of file names could conflict with existing files.
       
  2695  *
       
  2696  * @since 5.8.1
       
  2697  * @access private
       
  2698  *
       
  2699  * @param string[] $filenames Array of file names to check.
       
  2700  * @param string   $dir       The directory containing the files.
       
  2701  * @param array    $files     An array of existing files in the directory. May be empty.
       
  2702  * @return bool True if the tested file name could match an existing file, false otherwise.
       
  2703  */
       
  2704 function _wp_check_alternate_file_names( $filenames, $dir, $files ) {
       
  2705 	foreach ( $filenames as $filename ) {
       
  2706 		if ( file_exists( $dir . $filename ) ) {
       
  2707 			return true;
       
  2708 		}
       
  2709 
       
  2710 		if ( ! empty( $files ) && _wp_check_existing_file_names( $filename, $files ) ) {
       
  2711 			return true;
       
  2712 		}
       
  2713 	}
       
  2714 
       
  2715 	return false;
  2591 }
  2716 }
  2592 
  2717 
  2593 /**
  2718 /**
  2594  * Helper function to check if a file name could match an existing image sub-size file name.
  2719  * Helper function to check if a file name could match an existing image sub-size file name.
  2595  *
  2720  *
  2735 	clearstatcache();
  2860 	clearstatcache();
  2736 
  2861 
  2737 	// Compute the URL.
  2862 	// Compute the URL.
  2738 	$url = $upload['url'] . "/$filename";
  2863 	$url = $upload['url'] . "/$filename";
  2739 
  2864 
       
  2865 	if ( is_multisite() ) {
       
  2866 		clean_dirsize_cache( $new_file );
       
  2867 	}
       
  2868 
  2740 	/** This filter is documented in wp-admin/includes/file.php */
  2869 	/** This filter is documented in wp-admin/includes/file.php */
  2741 	return apply_filters(
  2870 	return apply_filters(
  2742 		'wp_handle_upload',
  2871 		'wp_handle_upload',
  2743 		array(
  2872 		array(
  2744 			'file'  => $new_file,
  2873 			'file'  => $new_file,
  2768 		}
  2897 		}
  2769 	}
  2898 	}
  2770 }
  2899 }
  2771 
  2900 
  2772 /**
  2901 /**
       
  2902  * Returns first matched extension for the mime-type,
       
  2903  * as mapped from wp_get_mime_types().
       
  2904  *
       
  2905  * @since 5.8.1
       
  2906  *
       
  2907  * @param string $mime_type
       
  2908  *
       
  2909  * @return string|false
       
  2910  */
       
  2911 function wp_get_default_extension_for_mime_type( $mime_type ) {
       
  2912 	$extensions = explode( '|', array_search( $mime_type, wp_get_mime_types(), true ) );
       
  2913 
       
  2914 	if ( empty( $extensions[0] ) ) {
       
  2915 		return false;
       
  2916 	}
       
  2917 
       
  2918 	return $extensions[0];
       
  2919 }
       
  2920 
       
  2921 /**
  2773  * Retrieve the file type from the file name.
  2922  * Retrieve the file type from the file name.
  2774  *
  2923  *
  2775  * You can optionally define the mime array, if needed.
  2924  * You can optionally define the mime array, if needed.
  2776  *
  2925  *
  2777  * @since 2.0.4
  2926  * @since 2.0.4
  2778  *
  2927  *
  2779  * @param string   $filename File name or path.
  2928  * @param string   $filename File name or path.
  2780  * @param string[] $mimes    Optional. Array of mime types keyed by their file extension regex.
  2929  * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
  2781  * @return array {
  2930  * @return array {
  2782  *     Values for the extension and mime type.
  2931  *     Values for the extension and mime type.
  2783  *
  2932  *
  2784  *     @type string|false $ext  File extension, or false if the file doesn't match a mime type.
  2933  *     @type string|false $ext  File extension, or false if the file doesn't match a mime type.
  2785  *     @type string|false $type File mime type, or false if the file doesn't match a mime type.
  2934  *     @type string|false $type File mime type, or false if the file doesn't match a mime type.
  2817  * @since 3.0.0
  2966  * @since 3.0.0
  2818  *
  2967  *
  2819  * @param string   $file     Full path to the file.
  2968  * @param string   $file     Full path to the file.
  2820  * @param string   $filename The name of the file (may differ from $file due to $file being
  2969  * @param string   $filename The name of the file (may differ from $file due to $file being
  2821  *                           in a tmp directory).
  2970  *                           in a tmp directory).
  2822  * @param string[] $mimes    Optional. Array of mime types keyed by their file extension regex.
  2971  * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
  2823  * @return array {
  2972  * @return array {
  2824  *     Values for the extension, mime type, and corrected filename.
  2973  *     Values for the extension, mime type, and corrected filename.
  2825  *
  2974  *
  2826  *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
  2975  *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
  2827  *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
  2976  *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
  2863 					'image/jpeg' => 'jpg',
  3012 					'image/jpeg' => 'jpg',
  2864 					'image/png'  => 'png',
  3013 					'image/png'  => 'png',
  2865 					'image/gif'  => 'gif',
  3014 					'image/gif'  => 'gif',
  2866 					'image/bmp'  => 'bmp',
  3015 					'image/bmp'  => 'bmp',
  2867 					'image/tiff' => 'tif',
  3016 					'image/tiff' => 'tif',
       
  3017 					'image/webp' => 'webp',
  2868 				)
  3018 				)
  2869 			);
  3019 			);
  2870 
  3020 
  2871 			// Replace whatever is after the last period in the filename with the correct extension.
  3021 			// Replace whatever is after the last period in the filename with the correct extension.
  2872 			if ( ! empty( $mime_to_ext[ $real_mime ] ) ) {
  3022 			if ( ! empty( $mime_to_ext[ $real_mime ] ) ) {
  2929 			if ( ! in_array(
  3079 			if ( ! in_array(
  2930 				$type,
  3080 				$type,
  2931 				array(
  3081 				array(
  2932 					'text/plain',
  3082 					'text/plain',
  2933 					'text/csv',
  3083 					'text/csv',
       
  3084 					'application/csv',
  2934 					'text/richtext',
  3085 					'text/richtext',
  2935 					'text/tsv',
  3086 					'text/tsv',
  2936 					'text/vtt',
  3087 					'text/vtt',
       
  3088 				),
       
  3089 				true
       
  3090 			)
       
  3091 			) {
       
  3092 				$type = false;
       
  3093 				$ext  = false;
       
  3094 			}
       
  3095 		} elseif ( 'application/csv' === $real_mime ) {
       
  3096 			// Special casing for CSV files.
       
  3097 			if ( ! in_array(
       
  3098 				$type,
       
  3099 				array(
       
  3100 					'text/csv',
       
  3101 					'text/plain',
       
  3102 					'application/csv',
  2937 				),
  3103 				),
  2938 				true
  3104 				true
  2939 			)
  3105 			)
  2940 			) {
  3106 			) {
  2941 				$type = false;
  3107 				$type = false;
  2982 	 * Filters the "real" file type of the given file.
  3148 	 * Filters the "real" file type of the given file.
  2983 	 *
  3149 	 *
  2984 	 * @since 3.0.0
  3150 	 * @since 3.0.0
  2985 	 * @since 5.1.0 The $real_mime parameter was added.
  3151 	 * @since 5.1.0 The $real_mime parameter was added.
  2986 	 *
  3152 	 *
  2987 	 * @param array       $wp_check_filetype_and_ext {
  3153 	 * @param array        $wp_check_filetype_and_ext {
  2988 	 *     Values for the extension, mime type, and corrected filename.
  3154 	 *     Values for the extension, mime type, and corrected filename.
  2989 	 *
  3155 	 *
  2990 	 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
  3156 	 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
  2991 	 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
  3157 	 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
  2992 	 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
  3158 	 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
  2993 	 * }
  3159 	 * }
  2994 	 * @param string      $file                      Full path to the file.
  3160 	 * @param string       $file                      Full path to the file.
  2995 	 * @param string      $filename                  The name of the file (may differ from $file due to
  3161 	 * @param string       $filename                  The name of the file (may differ from $file due to
  2996 	 *                                               $file being in a tmp directory).
  3162 	 *                                                $file being in a tmp directory).
  2997 	 * @param string[]    $mimes                     Array of mime types keyed by their file extension regex.
  3163 	 * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
  2998 	 * @param string|bool $real_mime                 The actual mime type or false if the type cannot be determined.
  3164 	 * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
  2999 	 */
  3165 	 */
  3000 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes, $real_mime );
  3166 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes, $real_mime );
  3001 }
  3167 }
  3002 
  3168 
  3003 /**
  3169 /**
  3004  * Returns the real mime type of an image file.
  3170  * Returns the real mime type of an image file.
  3005  *
  3171  *
  3006  * This depends on exif_imagetype() or getimagesize() to determine real mime types.
  3172  * This depends on exif_imagetype() or getimagesize() to determine real mime types.
  3007  *
  3173  *
  3008  * @since 4.7.1
  3174  * @since 4.7.1
       
  3175  * @since 5.8.0 Added support for WebP images.
  3009  *
  3176  *
  3010  * @param string $file Full path to the file.
  3177  * @param string $file Full path to the file.
  3011  * @return string|false The actual mime type or false if the type cannot be determined.
  3178  * @return string|false The actual mime type or false if the type cannot be determined.
  3012  */
  3179  */
  3013 function wp_get_image_mime( $file ) {
  3180 function wp_get_image_mime( $file ) {
  3019 	try {
  3186 	try {
  3020 		if ( is_callable( 'exif_imagetype' ) ) {
  3187 		if ( is_callable( 'exif_imagetype' ) ) {
  3021 			$imagetype = exif_imagetype( $file );
  3188 			$imagetype = exif_imagetype( $file );
  3022 			$mime      = ( $imagetype ) ? image_type_to_mime_type( $imagetype ) : false;
  3189 			$mime      = ( $imagetype ) ? image_type_to_mime_type( $imagetype ) : false;
  3023 		} elseif ( function_exists( 'getimagesize' ) ) {
  3190 		} elseif ( function_exists( 'getimagesize' ) ) {
  3024 			$imagesize = @getimagesize( $file );
  3191 			// Don't silence errors when in debug mode, unless running unit tests.
  3025 			$mime      = ( isset( $imagesize['mime'] ) ) ? $imagesize['mime'] : false;
  3192 			if ( defined( 'WP_DEBUG' ) && WP_DEBUG
       
  3193 				&& ! defined( 'WP_RUN_CORE_TESTS' )
       
  3194 			) {
       
  3195 				// Not using wp_getimagesize() here to avoid an infinite loop.
       
  3196 				$imagesize = getimagesize( $file );
       
  3197 			} else {
       
  3198 				// phpcs:ignore WordPress.PHP.NoSilencedErrors
       
  3199 				$imagesize = @getimagesize( $file );
       
  3200 			}
       
  3201 
       
  3202 			$mime = ( isset( $imagesize['mime'] ) ) ? $imagesize['mime'] : false;
  3026 		} else {
  3203 		} else {
  3027 			$mime = false;
  3204 			$mime = false;
  3028 		}
  3205 		}
       
  3206 
       
  3207 		if ( false !== $mime ) {
       
  3208 			return $mime;
       
  3209 		}
       
  3210 
       
  3211 		$handle = fopen( $file, 'rb' );
       
  3212 		if ( false === $handle ) {
       
  3213 			return false;
       
  3214 		}
       
  3215 
       
  3216 		$magic = fread( $handle, 12 );
       
  3217 		if ( false === $magic ) {
       
  3218 			return false;
       
  3219 		}
       
  3220 
       
  3221 		/*
       
  3222 		 * Add WebP fallback detection when image library doesn't support WebP.
       
  3223 		 * Note: detection values come from LibWebP, see
       
  3224 		 * https://github.com/webmproject/libwebp/blob/master/imageio/image_dec.c#L30
       
  3225 		 */
       
  3226 		$magic = bin2hex( $magic );
       
  3227 		if (
       
  3228 			// RIFF.
       
  3229 			( 0 === strpos( $magic, '52494646' ) ) &&
       
  3230 			// WEBP.
       
  3231 			( 16 === strpos( $magic, '57454250' ) )
       
  3232 		) {
       
  3233 			$mime = 'image/webp';
       
  3234 		}
       
  3235 
       
  3236 		fclose( $handle );
  3029 	} catch ( Exception $e ) {
  3237 	} catch ( Exception $e ) {
  3030 		$mime = false;
  3238 		$mime = false;
  3031 	}
  3239 	}
  3032 
  3240 
  3033 	return $mime;
  3241 	return $mime;
  3062 			'jpg|jpeg|jpe'                 => 'image/jpeg',
  3270 			'jpg|jpeg|jpe'                 => 'image/jpeg',
  3063 			'gif'                          => 'image/gif',
  3271 			'gif'                          => 'image/gif',
  3064 			'png'                          => 'image/png',
  3272 			'png'                          => 'image/png',
  3065 			'bmp'                          => 'image/bmp',
  3273 			'bmp'                          => 'image/bmp',
  3066 			'tiff|tif'                     => 'image/tiff',
  3274 			'tiff|tif'                     => 'image/tiff',
       
  3275 			'webp'                         => 'image/webp',
  3067 			'ico'                          => 'image/x-icon',
  3276 			'ico'                          => 'image/x-icon',
  3068 			'heic'                         => 'image/heic',
  3277 			'heic'                         => 'image/heic',
  3069 			// Video formats.
  3278 			// Video formats.
  3070 			'asf|asx'                      => 'video/x-ms-asf',
  3279 			'asf|asx'                      => 'video/x-ms-asf',
  3071 			'wmv'                          => 'video/x-ms-wmv',
  3280 			'wmv'                          => 'video/x-ms-wmv',
  3183 	 * @param array[] $ext2type Multi-dimensional array of file extensions types keyed by the type of file.
  3392 	 * @param array[] $ext2type Multi-dimensional array of file extensions types keyed by the type of file.
  3184 	 */
  3393 	 */
  3185 	return apply_filters(
  3394 	return apply_filters(
  3186 		'ext2type',
  3395 		'ext2type',
  3187 		array(
  3396 		array(
  3188 			'image'       => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic' ),
  3397 			'image'       => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic', 'webp' ),
  3189 			'audio'       => array( 'aac', 'ac3', 'aif', 'aiff', 'flac', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
  3398 			'audio'       => array( 'aac', 'ac3', 'aif', 'aiff', 'flac', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
  3190 			'video'       => array( '3g2', '3gp', '3gpp', 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
  3399 			'video'       => array( '3g2', '3gp', '3gpp', 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
  3191 			'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'xps', 'oxps', 'rtf', 'wp', 'wpd', 'psd', 'xcf' ),
  3400 			'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'xps', 'oxps', 'rtf', 'wp', 'wpd', 'psd', 'xcf' ),
  3192 			'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ),
  3401 			'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ),
  3193 			'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
  3402 			'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
  3343 		 * @since 5.1.0
  3552 		 * @since 5.1.0
  3344 		 *
  3553 		 *
  3345 		 * @param callable $function Callback function name.
  3554 		 * @param callable $function Callback function name.
  3346 		 */
  3555 		 */
  3347 		$function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
  3556 		$function = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
  3348 	} elseif ( wp_is_jsonp_request() ) {
  3557 	} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST && wp_is_jsonp_request() ) {
  3349 		/**
  3558 		/**
  3350 		 * Filters the callback for killing WordPress execution for JSONP requests.
  3559 		 * Filters the callback for killing WordPress execution for JSONP REST requests.
  3351 		 *
  3560 		 *
  3352 		 * @since 5.2.0
  3561 		 * @since 5.2.0
  3353 		 *
  3562 		 *
  3354 		 * @param callable $function Callback function name.
  3563 		 * @param callable $function Callback function name.
  3355 		 */
  3564 		 */
  3410 		if ( ! empty( $parsed_args['additional_errors'] ) ) {
  3619 		if ( ! empty( $parsed_args['additional_errors'] ) ) {
  3411 			$message = array_merge(
  3620 			$message = array_merge(
  3412 				array( $message ),
  3621 				array( $message ),
  3413 				wp_list_pluck( $parsed_args['additional_errors'], 'message' )
  3622 				wp_list_pluck( $parsed_args['additional_errors'], 'message' )
  3414 			);
  3623 			);
  3415 			$message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $message ) . "</li>\n\t</ul>";
  3624 			$message = "<ul>\n\t\t<li>" . implode( "</li>\n\t\t<li>", $message ) . "</li>\n\t</ul>";
  3416 		}
  3625 		}
  3417 
  3626 
  3418 		$message = sprintf(
  3627 		$message = sprintf(
  3419 			'<div class="wp-die-message">%s</div>',
  3628 			'<div class="wp-die-message">%s</div>',
  3420 			$message
  3629 			$message
  3459 <html <?php echo $dir_attr; ?>>
  3668 <html <?php echo $dir_attr; ?>>
  3460 <head>
  3669 <head>
  3461 	<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $parsed_args['charset']; ?>" />
  3670 	<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $parsed_args['charset']; ?>" />
  3462 	<meta name="viewport" content="width=device-width">
  3671 	<meta name="viewport" content="width=device-width">
  3463 		<?php
  3672 		<?php
  3464 		if ( function_exists( 'wp_no_robots' ) ) {
  3673 		if ( function_exists( 'wp_robots' ) && function_exists( 'wp_robots_no_robots' ) && function_exists( 'add_filter' ) ) {
  3465 			wp_no_robots();
  3674 			add_filter( 'wp_robots', 'wp_robots_no_robots' );
       
  3675 			wp_robots();
  3466 		}
  3676 		}
  3467 		?>
  3677 		?>
  3468 	<title><?php echo $title; ?></title>
  3678 	<title><?php echo $title; ?></title>
  3469 	<style type="text/css">
  3679 	<style type="text/css">
  3470 		html {
  3680 		html {
  3471 			background: #f1f1f1;
  3681 			background: #f1f1f1;
  3472 		}
  3682 		}
  3473 		body {
  3683 		body {
  3474 			background: #fff;
  3684 			background: #fff;
       
  3685 			border: 1px solid #ccd0d4;
  3475 			color: #444;
  3686 			color: #444;
  3476 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  3687 			font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
  3477 			margin: 2em auto;
  3688 			margin: 2em auto;
  3478 			padding: 1em 2em;
  3689 			padding: 1em 2em;
  3479 			max-width: 700px;
  3690 			max-width: 700px;
  3480 			-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.13);
  3691 			-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
  3481 			box-shadow: 0 1px 3px rgba(0, 0, 0, 0.13);
  3692 			box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
  3482 		}
  3693 		}
  3483 		h1 {
  3694 		h1 {
  3484 			border-bottom: 1px solid #dadada;
  3695 			border-bottom: 1px solid #dadada;
  3485 			clear: both;
  3696 			clear: both;
  3486 			color: #666;
  3697 			color: #666;
  3521 				0 0 0 1px #5b9dd9,
  3732 				0 0 0 1px #5b9dd9,
  3522 				0 0 2px 1px rgba(30, 140, 190, 0.8);
  3733 				0 0 2px 1px rgba(30, 140, 190, 0.8);
  3523 			outline: none;
  3734 			outline: none;
  3524 		}
  3735 		}
  3525 		.button {
  3736 		.button {
  3526 			background: #f7f7f7;
  3737 			background: #f3f5f6;
  3527 			border: 1px solid #ccc;
  3738 			border: 1px solid #016087;
  3528 			color: #555;
  3739 			color: #016087;
  3529 			display: inline-block;
  3740 			display: inline-block;
  3530 			text-decoration: none;
  3741 			text-decoration: none;
  3531 			font-size: 13px;
  3742 			font-size: 13px;
  3532 			line-height: 2;
  3743 			line-height: 2;
  3533 			height: 28px;
  3744 			height: 28px;
  3540 			white-space: nowrap;
  3751 			white-space: nowrap;
  3541 			-webkit-box-sizing: border-box;
  3752 			-webkit-box-sizing: border-box;
  3542 			-moz-box-sizing:    border-box;
  3753 			-moz-box-sizing:    border-box;
  3543 			box-sizing:         border-box;
  3754 			box-sizing:         border-box;
  3544 
  3755 
  3545 			-webkit-box-shadow: 0 1px 0 #ccc;
       
  3546 			box-shadow: 0 1px 0 #ccc;
       
  3547 			vertical-align: top;
  3756 			vertical-align: top;
  3548 		}
  3757 		}
  3549 
  3758 
  3550 		.button.button-large {
  3759 		.button.button-large {
  3551 			height: 30px;
  3760 			line-height: 2.30769231;
  3552 			line-height: 2.15384615;
  3761 			min-height: 32px;
  3553 			padding: 0 12px 2px;
  3762 			padding: 0 12px;
  3554 		}
  3763 		}
  3555 
  3764 
  3556 		.button:hover,
  3765 		.button:hover,
  3557 		.button:focus {
  3766 		.button:focus {
  3558 			background: #fafafa;
  3767 			background: #f1f1f1;
  3559 			border-color: #999;
       
  3560 			color: #23282d;
       
  3561 		}
  3768 		}
  3562 
  3769 
  3563 		.button:focus {
  3770 		.button:focus {
  3564 			border-color: #5b9dd9;
  3771 			background: #f3f5f6;
  3565 			-webkit-box-shadow: 0 0 3px rgba(0, 115, 170, 0.8);
  3772 			border-color: #007cba;
  3566 			box-shadow: 0 0 3px rgba(0, 115, 170, 0.8);
  3773 			-webkit-box-shadow: 0 0 0 1px #007cba;
  3567 			outline: none;
  3774 			box-shadow: 0 0 0 1px #007cba;
       
  3775 			color: #016087;
       
  3776 			outline: 2px solid transparent;
       
  3777 			outline-offset: 0;
  3568 		}
  3778 		}
  3569 
  3779 
  3570 		.button:active {
  3780 		.button:active {
  3571 			background: #eee;
  3781 			background: #f3f5f6;
  3572 			border-color: #999;
  3782 			border-color: #7e8993;
  3573 			-webkit-box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
  3783 			-webkit-box-shadow: none;
  3574 			box-shadow: inset 0 2px 5px -3px rgba(0, 0, 0, 0.5);
  3784 			box-shadow: none;
  3575 		}
  3785 		}
  3576 
  3786 
  3577 		<?php
  3787 		<?php
  3578 		if ( 'rtl' === $text_direction ) {
  3788 		if ( 'rtl' === $text_direction ) {
  3579 			echo 'body { font-family: Tahoma, Arial; }';
  3789 			echo 'body { font-family: Tahoma, Arial; }';
  4053 /**
  4263 /**
  4054  * Send a JSON response back to an Ajax request.
  4264  * Send a JSON response back to an Ajax request.
  4055  *
  4265  *
  4056  * @since 3.5.0
  4266  * @since 3.5.0
  4057  * @since 4.7.0 The `$status_code` parameter was added.
  4267  * @since 4.7.0 The `$status_code` parameter was added.
       
  4268  * @since 5.6.0 The `$options` parameter was added.
  4058  *
  4269  *
  4059  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
  4270  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
  4060  *                           then print and die.
  4271  *                           then print and die.
  4061  * @param int   $status_code The HTTP status code to output.
  4272  * @param int   $status_code Optional. The HTTP status code to output. Default null.
  4062  */
  4273  * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
  4063 function wp_send_json( $response, $status_code = null ) {
  4274  */
       
  4275 function wp_send_json( $response, $status_code = null, $options = 0 ) {
  4064 	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
  4276 	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
  4065 		_doing_it_wrong(
  4277 		_doing_it_wrong(
  4066 			__FUNCTION__,
  4278 			__FUNCTION__,
  4067 			sprintf(
  4279 			sprintf(
  4068 				/* translators: 1: WP_REST_Response, 2: WP_Error */
  4280 				/* translators: 1: WP_REST_Response, 2: WP_Error */
  4079 		if ( null !== $status_code ) {
  4291 		if ( null !== $status_code ) {
  4080 			status_header( $status_code );
  4292 			status_header( $status_code );
  4081 		}
  4293 		}
  4082 	}
  4294 	}
  4083 
  4295 
  4084 	echo wp_json_encode( $response );
  4296 	echo wp_json_encode( $response, $options );
  4085 
  4297 
  4086 	if ( wp_doing_ajax() ) {
  4298 	if ( wp_doing_ajax() ) {
  4087 		wp_die(
  4299 		wp_die(
  4088 			'',
  4300 			'',
  4089 			'',
  4301 			'',
  4099 /**
  4311 /**
  4100  * Send a JSON response back to an Ajax request, indicating success.
  4312  * Send a JSON response back to an Ajax request, indicating success.
  4101  *
  4313  *
  4102  * @since 3.5.0
  4314  * @since 3.5.0
  4103  * @since 4.7.0 The `$status_code` parameter was added.
  4315  * @since 4.7.0 The `$status_code` parameter was added.
  4104  *
  4316  * @since 5.6.0 The `$options` parameter was added.
  4105  * @param mixed $data        Data to encode as JSON, then print and die.
  4317  *
  4106  * @param int   $status_code The HTTP status code to output.
  4318  * @param mixed $data        Optional. Data to encode as JSON, then print and die. Default null.
  4107  */
  4319  * @param int   $status_code Optional. The HTTP status code to output. Default null.
  4108 function wp_send_json_success( $data = null, $status_code = null ) {
  4320  * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
       
  4321  */
       
  4322 function wp_send_json_success( $data = null, $status_code = null, $options = 0 ) {
  4109 	$response = array( 'success' => true );
  4323 	$response = array( 'success' => true );
  4110 
  4324 
  4111 	if ( isset( $data ) ) {
  4325 	if ( isset( $data ) ) {
  4112 		$response['data'] = $data;
  4326 		$response['data'] = $data;
  4113 	}
  4327 	}
  4114 
  4328 
  4115 	wp_send_json( $response, $status_code );
  4329 	wp_send_json( $response, $status_code, $options );
  4116 }
  4330 }
  4117 
  4331 
  4118 /**
  4332 /**
  4119  * Send a JSON response back to an Ajax request, indicating failure.
  4333  * Send a JSON response back to an Ajax request, indicating failure.
  4120  *
  4334  *
  4124  * without further processing.
  4338  * without further processing.
  4125  *
  4339  *
  4126  * @since 3.5.0
  4340  * @since 3.5.0
  4127  * @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in.
  4341  * @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in.
  4128  * @since 4.7.0 The `$status_code` parameter was added.
  4342  * @since 4.7.0 The `$status_code` parameter was added.
  4129  *
  4343  * @since 5.6.0 The `$options` parameter was added.
  4130  * @param mixed $data        Data to encode as JSON, then print and die.
  4344  *
  4131  * @param int   $status_code The HTTP status code to output.
  4345  * @param mixed $data        Optional. Data to encode as JSON, then print and die. Default null.
  4132  */
  4346  * @param int   $status_code Optional. The HTTP status code to output. Default null.
  4133 function wp_send_json_error( $data = null, $status_code = null ) {
  4347  * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
       
  4348  */
       
  4349 function wp_send_json_error( $data = null, $status_code = null, $options = 0 ) {
  4134 	$response = array( 'success' => false );
  4350 	$response = array( 'success' => false );
  4135 
  4351 
  4136 	if ( isset( $data ) ) {
  4352 	if ( isset( $data ) ) {
  4137 		if ( is_wp_error( $data ) ) {
  4353 		if ( is_wp_error( $data ) ) {
  4138 			$result = array();
  4354 			$result = array();
  4149 		} else {
  4365 		} else {
  4150 			$response['data'] = $data;
  4366 			$response['data'] = $data;
  4151 		}
  4367 		}
  4152 	}
  4368 	}
  4153 
  4369 
  4154 	wp_send_json( $response, $status_code );
  4370 	wp_send_json( $response, $status_code, $options );
  4155 }
  4371 }
  4156 
  4372 
  4157 /**
  4373 /**
  4158  * Checks that a JSONP callback is a valid JavaScript callback name.
  4374  * Checks that a JSONP callback is a valid JavaScript callback name.
  4159  *
  4375  *
  4395 	$wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
  4611 	$wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
  4396 
  4612 
  4397 }
  4613 }
  4398 
  4614 
  4399 /**
  4615 /**
  4400  * Merge user defined arguments into defaults array.
  4616  * Merges user defined arguments into defaults array.
  4401  *
  4617  *
  4402  * This function is used throughout WordPress to allow for both string or array
  4618  * This function is used throughout WordPress to allow for both string or array
  4403  * to be merged into another array.
  4619  * to be merged into another array.
  4404  *
  4620  *
  4405  * @since 2.2.0
  4621  * @since 2.2.0
  4424 	}
  4640 	}
  4425 	return $parsed_args;
  4641 	return $parsed_args;
  4426 }
  4642 }
  4427 
  4643 
  4428 /**
  4644 /**
  4429  * Cleans up an array, comma- or space-separated list of scalar values.
  4645  * Converts a comma- or space-separated list of scalar values to an array.
  4430  *
  4646  *
  4431  * @since 5.1.0
  4647  * @since 5.1.0
  4432  *
  4648  *
  4433  * @param array|string $list List of values.
  4649  * @param array|string $list List of values.
  4434  * @return array Sanitized array of values.
  4650  * @return array Array of values.
  4435  */
  4651  */
  4436 function wp_parse_list( $list ) {
  4652 function wp_parse_list( $list ) {
  4437 	if ( ! is_array( $list ) ) {
  4653 	if ( ! is_array( $list ) ) {
  4438 		return preg_split( '/[\s,]+/', $list, -1, PREG_SPLIT_NO_EMPTY );
  4654 		return preg_split( '/[\s,]+/', $list, -1, PREG_SPLIT_NO_EMPTY );
  4439 	}
  4655 	}
  4440 
  4656 
  4441 	return $list;
  4657 	return $list;
  4442 }
  4658 }
  4443 
  4659 
  4444 /**
  4660 /**
  4445  * Clean up an array, comma- or space-separated list of IDs.
  4661  * Cleans up an array, comma- or space-separated list of IDs.
  4446  *
  4662  *
  4447  * @since 3.0.0
  4663  * @since 3.0.0
       
  4664  * @since 5.1.0 Refactored to use wp_parse_list().
  4448  *
  4665  *
  4449  * @param array|string $list List of IDs.
  4666  * @param array|string $list List of IDs.
  4450  * @return int[] Sanitized array of IDs.
  4667  * @return int[] Sanitized array of IDs.
  4451  */
  4668  */
  4452 function wp_parse_id_list( $list ) {
  4669 function wp_parse_id_list( $list ) {
  4454 
  4671 
  4455 	return array_unique( array_map( 'absint', $list ) );
  4672 	return array_unique( array_map( 'absint', $list ) );
  4456 }
  4673 }
  4457 
  4674 
  4458 /**
  4675 /**
  4459  * Clean up an array, comma- or space-separated list of slugs.
  4676  * Cleans up an array, comma- or space-separated list of slugs.
  4460  *
  4677  *
  4461  * @since 4.7.0
  4678  * @since 4.7.0
       
  4679  * @since 5.1.0 Refactored to use wp_parse_list().
  4462  *
  4680  *
  4463  * @param array|string $list List of slugs.
  4681  * @param array|string $list List of slugs.
  4464  * @return string[] Sanitized array of slugs.
  4682  * @return string[] Sanitized array of slugs.
  4465  */
  4683  */
  4466 function wp_parse_slug_list( $list ) {
  4684 function wp_parse_slug_list( $list ) {
  4478  * @param array $keys  The list of keys.
  4696  * @param array $keys  The list of keys.
  4479  * @return array The array slice.
  4697  * @return array The array slice.
  4480  */
  4698  */
  4481 function wp_array_slice_assoc( $array, $keys ) {
  4699 function wp_array_slice_assoc( $array, $keys ) {
  4482 	$slice = array();
  4700 	$slice = array();
       
  4701 
  4483 	foreach ( $keys as $key ) {
  4702 	foreach ( $keys as $key ) {
  4484 		if ( isset( $array[ $key ] ) ) {
  4703 		if ( isset( $array[ $key ] ) ) {
  4485 			$slice[ $key ] = $array[ $key ];
  4704 			$slice[ $key ] = $array[ $key ];
  4486 		}
  4705 		}
  4487 	}
  4706 	}
  4488 
  4707 
  4489 	return $slice;
  4708 	return $slice;
  4490 }
  4709 }
  4491 
  4710 
  4492 /**
  4711 /**
       
  4712  * Accesses an array in depth based on a path of keys.
       
  4713  *
       
  4714  * It is the PHP equivalent of JavaScript's `lodash.get()` and mirroring it may help other components
       
  4715  * retain some symmetry between client and server implementations.
       
  4716  *
       
  4717  * Example usage:
       
  4718  *
       
  4719  *     $array = array(
       
  4720  *         'a' => array(
       
  4721  *             'b' => array(
       
  4722  *                 'c' => 1,
       
  4723  *             ),
       
  4724  *         ),
       
  4725  *     );
       
  4726  *     _wp_array_get( $array, array( 'a', 'b', 'c' ) );
       
  4727  *
       
  4728  * @internal
       
  4729  *
       
  4730  * @since 5.6.0
       
  4731  * @access private
       
  4732  *
       
  4733  * @param array $array   An array from which we want to retrieve some information.
       
  4734  * @param array $path    An array of keys describing the path with which to retrieve information.
       
  4735  * @param mixed $default The return value if the path does not exist within the array,
       
  4736  *                       or if `$array` or `$path` are not arrays.
       
  4737  * @return mixed The value from the path specified.
       
  4738  */
       
  4739 function _wp_array_get( $array, $path, $default = null ) {
       
  4740 	// Confirm $path is valid.
       
  4741 	if ( ! is_array( $path ) || 0 === count( $path ) ) {
       
  4742 		return $default;
       
  4743 	}
       
  4744 
       
  4745 	foreach ( $path as $path_element ) {
       
  4746 		if (
       
  4747 			! is_array( $array ) ||
       
  4748 			( ! is_string( $path_element ) && ! is_integer( $path_element ) && ! is_null( $path_element ) ) ||
       
  4749 			! array_key_exists( $path_element, $array )
       
  4750 		) {
       
  4751 			return $default;
       
  4752 		}
       
  4753 		$array = $array[ $path_element ];
       
  4754 	}
       
  4755 
       
  4756 	return $array;
       
  4757 }
       
  4758 
       
  4759 /**
       
  4760  * Sets an array in depth based on a path of keys.
       
  4761  *
       
  4762  * It is the PHP equivalent of JavaScript's `lodash.set()` and mirroring it may help other components
       
  4763  * retain some symmetry between client and server implementations.
       
  4764  *
       
  4765  * Example usage:
       
  4766  *
       
  4767  *     $array = array();
       
  4768  *     _wp_array_set( $array, array( 'a', 'b', 'c', 1 ) );
       
  4769  *
       
  4770  *     $array becomes:
       
  4771  *     array(
       
  4772  *         'a' => array(
       
  4773  *             'b' => array(
       
  4774  *                 'c' => 1,
       
  4775  *             ),
       
  4776  *         ),
       
  4777  *     );
       
  4778  *
       
  4779  * @internal
       
  4780  *
       
  4781  * @since 5.8.0
       
  4782  * @access private
       
  4783  *
       
  4784  * @param array $array An array that we want to mutate to include a specific value in a path.
       
  4785  * @param array $path  An array of keys describing the path that we want to mutate.
       
  4786  * @param mixed $value The value that will be set.
       
  4787  */
       
  4788 function _wp_array_set( &$array, $path, $value = null ) {
       
  4789 	// Confirm $array is valid.
       
  4790 	if ( ! is_array( $array ) ) {
       
  4791 		return;
       
  4792 	}
       
  4793 
       
  4794 	// Confirm $path is valid.
       
  4795 	if ( ! is_array( $path ) ) {
       
  4796 		return;
       
  4797 	}
       
  4798 
       
  4799 	$path_length = count( $path );
       
  4800 
       
  4801 	if ( 0 === $path_length ) {
       
  4802 		return;
       
  4803 	}
       
  4804 
       
  4805 	foreach ( $path as $path_element ) {
       
  4806 		if (
       
  4807 			! is_string( $path_element ) && ! is_integer( $path_element ) &&
       
  4808 			! is_null( $path_element )
       
  4809 		) {
       
  4810 			return;
       
  4811 		}
       
  4812 	}
       
  4813 
       
  4814 	for ( $i = 0; $i < $path_length - 1; ++$i ) {
       
  4815 		$path_element = $path[ $i ];
       
  4816 		if (
       
  4817 			! array_key_exists( $path_element, $array ) ||
       
  4818 			! is_array( $array[ $path_element ] )
       
  4819 		) {
       
  4820 			$array[ $path_element ] = array();
       
  4821 		}
       
  4822 		$array = &$array[ $path_element ]; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.VariableRedeclaration
       
  4823 	}
       
  4824 
       
  4825 	$array[ $path[ $i ] ] = $value;
       
  4826 }
       
  4827 
       
  4828 /**
       
  4829  * This function is trying to replicate what
       
  4830  * lodash's kebabCase (JS library) does in the client.
       
  4831  *
       
  4832  * The reason we need this function is that we do some processing
       
  4833  * in both the client and the server (e.g.: we generate
       
  4834  * preset classes from preset slugs) that needs to
       
  4835  * create the same output.
       
  4836  *
       
  4837  * We can't remove or update the client's library due to backward compatibility
       
  4838  * (some of the output of lodash's kebabCase is saved in the post content).
       
  4839  * We have to make the server behave like the client.
       
  4840  *
       
  4841  * Changes to this function should follow updates in the client
       
  4842  * with the same logic.
       
  4843  *
       
  4844  * @link https://github.com/lodash/lodash/blob/4.17/dist/lodash.js#L14369
       
  4845  * @link https://github.com/lodash/lodash/blob/4.17/dist/lodash.js#L278
       
  4846  * @link https://github.com/lodash-php/lodash-php/blob/master/src/String/kebabCase.php
       
  4847  * @link https://github.com/lodash-php/lodash-php/blob/master/src/internal/unicodeWords.php
       
  4848  *
       
  4849  * @param string $string The string to kebab-case.
       
  4850  *
       
  4851  * @return string kebab-cased-string.
       
  4852  */
       
  4853 function _wp_to_kebab_case( $string ) {
       
  4854 	//phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
       
  4855 	// ignore the camelCase names for variables so the names are the same as lodash
       
  4856 	// so comparing and porting new changes is easier.
       
  4857 
       
  4858 	/*
       
  4859 	 * Some notable things we've removed compared to the lodash version are:
       
  4860 	 *
       
  4861 	 * - non-alphanumeric characters: rsAstralRange, rsEmoji, etc
       
  4862 	 * - the groups that processed the apostrophe, as it's removed before passing the string to preg_match: rsApos, rsOptContrLower, and rsOptContrUpper
       
  4863 	 *
       
  4864 	 */
       
  4865 
       
  4866 	/** Used to compose unicode character classes. */
       
  4867 	$rsLowerRange       = 'a-z\\xdf-\\xf6\\xf8-\\xff';
       
  4868 	$rsNonCharRange     = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf';
       
  4869 	$rsPunctuationRange = '\\x{2000}-\\x{206f}';
       
  4870 	$rsSpaceRange       = ' \\t\\x0b\\f\\xa0\\x{feff}\\n\\r\\x{2028}\\x{2029}\\x{1680}\\x{180e}\\x{2000}\\x{2001}\\x{2002}\\x{2003}\\x{2004}\\x{2005}\\x{2006}\\x{2007}\\x{2008}\\x{2009}\\x{200a}\\x{202f}\\x{205f}\\x{3000}';
       
  4871 	$rsUpperRange       = 'A-Z\\xc0-\\xd6\\xd8-\\xde';
       
  4872 	$rsBreakRange       = $rsNonCharRange . $rsPunctuationRange . $rsSpaceRange;
       
  4873 
       
  4874 	/** Used to compose unicode capture groups. */
       
  4875 	$rsBreak  = '[' . $rsBreakRange . ']';
       
  4876 	$rsDigits = '\\d+'; // The last lodash version in GitHub uses a single digit here and expands it when in use.
       
  4877 	$rsLower  = '[' . $rsLowerRange . ']';
       
  4878 	$rsMisc   = '[^' . $rsBreakRange . $rsDigits . $rsLowerRange . $rsUpperRange . ']';
       
  4879 	$rsUpper  = '[' . $rsUpperRange . ']';
       
  4880 
       
  4881 	/** Used to compose unicode regexes. */
       
  4882 	$rsMiscLower = '(?:' . $rsLower . '|' . $rsMisc . ')';
       
  4883 	$rsMiscUpper = '(?:' . $rsUpper . '|' . $rsMisc . ')';
       
  4884 	$rsOrdLower  = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])';
       
  4885 	$rsOrdUpper  = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])';
       
  4886 
       
  4887 	$regexp = '/' . implode(
       
  4888 		'|',
       
  4889 		array(
       
  4890 			$rsUpper . '?' . $rsLower . '+' . '(?=' . implode( '|', array( $rsBreak, $rsUpper, '$' ) ) . ')',
       
  4891 			$rsMiscUpper . '+' . '(?=' . implode( '|', array( $rsBreak, $rsUpper . $rsMiscLower, '$' ) ) . ')',
       
  4892 			$rsUpper . '?' . $rsMiscLower . '+',
       
  4893 			$rsUpper . '+',
       
  4894 			$rsOrdUpper,
       
  4895 			$rsOrdLower,
       
  4896 			$rsDigits,
       
  4897 		)
       
  4898 	) . '/u';
       
  4899 
       
  4900 	preg_match_all( $regexp, str_replace( "'", '', $string ), $matches );
       
  4901 	return strtolower( implode( '-', $matches[0] ) );
       
  4902 	//phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
       
  4903 }
       
  4904 
       
  4905 /**
  4493  * Determines if the variable is a numeric-indexed array.
  4906  * Determines if the variable is a numeric-indexed array.
  4494  *
  4907  *
  4495  * @since 4.4.0
  4908  * @since 4.4.0
  4496  *
  4909  *
  4497  * @param mixed $data Variable to check.
  4910  * @param mixed $data Variable to check.
  4502 		return false;
  4915 		return false;
  4503 	}
  4916 	}
  4504 
  4917 
  4505 	$keys        = array_keys( $data );
  4918 	$keys        = array_keys( $data );
  4506 	$string_keys = array_filter( $keys, 'is_string' );
  4919 	$string_keys = array_filter( $keys, 'is_string' );
       
  4920 
  4507 	return count( $string_keys ) === 0;
  4921 	return count( $string_keys ) === 0;
  4508 }
  4922 }
  4509 
  4923 
  4510 /**
  4924 /**
  4511  * Filters a list of objects, based on a set of key => value arguments.
  4925  * Filters a list of objects, based on a set of key => value arguments.
       
  4926  *
       
  4927  * Retrieves the objects from the list that match the given arguments.
       
  4928  * Key represents property name, and value represents property value.
       
  4929  *
       
  4930  * If an object has more properties than those specified in arguments,
       
  4931  * that will not disqualify it. When using the 'AND' operator,
       
  4932  * any missing properties will disqualify it.
       
  4933  *
       
  4934  * When using the `$field` argument, this function can also retrieve
       
  4935  * a particular field from all matching objects, whereas wp_list_filter()
       
  4936  * only does the filtering.
  4512  *
  4937  *
  4513  * @since 3.0.0
  4938  * @since 3.0.0
  4514  * @since 4.7.0 Uses `WP_List_Util` class.
  4939  * @since 4.7.0 Uses `WP_List_Util` class.
  4515  *
  4940  *
  4516  * @param array       $list     An array of objects to filter
  4941  * @param array       $list     An array of objects to filter.
  4517  * @param array       $args     Optional. An array of key => value arguments to match
  4942  * @param array       $args     Optional. An array of key => value arguments to match
  4518  *                              against each object. Default empty array.
  4943  *                              against each object. Default empty array.
  4519  * @param string      $operator Optional. The logical operation to perform. 'or' means
  4944  * @param string      $operator Optional. The logical operation to perform. 'AND' means
  4520  *                              only one element from the array needs to match; 'and'
  4945  *                              all elements from the array must match. 'OR' means only
  4521  *                              means all elements must match; 'not' means no elements may
  4946  *                              one element needs to match. 'NOT' means no elements may
  4522  *                              match. Default 'and'.
  4947  *                              match. Default 'AND'.
  4523  * @param bool|string $field    A field from the object to place instead of the entire object.
  4948  * @param bool|string $field    Optional. A field from the object to place instead
  4524  *                              Default false.
  4949  *                              of the entire object. Default false.
  4525  * @return array A list of objects or object fields.
  4950  * @return array A list of objects or object fields.
  4526  */
  4951  */
  4527 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
  4952 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
  4528 	if ( ! is_array( $list ) ) {
  4953 	if ( ! is_array( $list ) ) {
  4529 		return array();
  4954 		return array();
  4540 	return $util->get_output();
  4965 	return $util->get_output();
  4541 }
  4966 }
  4542 
  4967 
  4543 /**
  4968 /**
  4544  * Filters a list of objects, based on a set of key => value arguments.
  4969  * Filters a list of objects, based on a set of key => value arguments.
       
  4970  *
       
  4971  * Retrieves the objects from the list that match the given arguments.
       
  4972  * Key represents property name, and value represents property value.
       
  4973  *
       
  4974  * If an object has more properties than those specified in arguments,
       
  4975  * that will not disqualify it. When using the 'AND' operator,
       
  4976  * any missing properties will disqualify it.
       
  4977  *
       
  4978  * If you want to retrieve a particular field from all matching objects,
       
  4979  * use wp_filter_object_list() instead.
  4545  *
  4980  *
  4546  * @since 3.1.0
  4981  * @since 3.1.0
  4547  * @since 4.7.0 Uses `WP_List_Util` class.
  4982  * @since 4.7.0 Uses `WP_List_Util` class.
  4548  *
  4983  *
  4549  * @param array  $list     An array of objects to filter.
  4984  * @param array  $list     An array of objects to filter.
  4559 	if ( ! is_array( $list ) ) {
  4994 	if ( ! is_array( $list ) ) {
  4560 		return array();
  4995 		return array();
  4561 	}
  4996 	}
  4562 
  4997 
  4563 	$util = new WP_List_Util( $list );
  4998 	$util = new WP_List_Util( $list );
       
  4999 
  4564 	return $util->filter( $args, $operator );
  5000 	return $util->filter( $args, $operator );
  4565 }
  5001 }
  4566 
  5002 
  4567 /**
  5003 /**
  4568  * Pluck a certain field out of each object in a list.
  5004  * Pluck a certain field out of each object in a list.
  4572  *
  5008  *
  4573  * @since 3.1.0
  5009  * @since 3.1.0
  4574  * @since 4.0.0 $index_key parameter added.
  5010  * @since 4.0.0 $index_key parameter added.
  4575  * @since 4.7.0 Uses `WP_List_Util` class.
  5011  * @since 4.7.0 Uses `WP_List_Util` class.
  4576  *
  5012  *
  4577  * @param array      $list      List of objects or arrays
  5013  * @param array      $list      List of objects or arrays.
  4578  * @param int|string $field     Field from the object to place instead of the entire object
  5014  * @param int|string $field     Field from the object to place instead of the entire object.
  4579  * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
  5015  * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
  4580  *                              Default null.
  5016  *                              Default null.
  4581  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  5017  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  4582  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  5018  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
  4583  *               `$list` will be preserved in the results.
  5019  *               `$list` will be preserved in the results.
  4584  */
  5020  */
  4585 function wp_list_pluck( $list, $field, $index_key = null ) {
  5021 function wp_list_pluck( $list, $field, $index_key = null ) {
  4586 	$util = new WP_List_Util( $list );
  5022 	$util = new WP_List_Util( $list );
       
  5023 
  4587 	return $util->pluck( $field, $index_key );
  5024 	return $util->pluck( $field, $index_key );
  4588 }
  5025 }
  4589 
  5026 
  4590 /**
  5027 /**
  4591  * Sorts a list of objects, based on one or more orderby arguments.
  5028  * Sorts a list of objects, based on one or more orderby arguments.
  4604 	if ( ! is_array( $list ) ) {
  5041 	if ( ! is_array( $list ) ) {
  4605 		return array();
  5042 		return array();
  4606 	}
  5043 	}
  4607 
  5044 
  4608 	$util = new WP_List_Util( $list );
  5045 	$util = new WP_List_Util( $list );
       
  5046 
  4609 	return $util->sort( $orderby, $order, $preserve_keys );
  5047 	return $util->sort( $orderby, $order, $preserve_keys );
  4610 }
  5048 }
  4611 
  5049 
  4612 /**
  5050 /**
  4613  * Determines if Widgets library should be loaded.
  5051  * Determines if Widgets library should be loaded.
  4715  *
  5153  *
  4716  * @param mixed $maybeint Data you wish to have converted to a non-negative integer.
  5154  * @param mixed $maybeint Data you wish to have converted to a non-negative integer.
  4717  * @return int A non-negative integer.
  5155  * @return int A non-negative integer.
  4718  */
  5156  */
  4719 function absint( $maybeint ) {
  5157 function absint( $maybeint ) {
  4720 	return abs( intval( $maybeint ) );
  5158 	return abs( (int) $maybeint );
  4721 }
  5159 }
  4722 
  5160 
  4723 /**
  5161 /**
  4724  * Mark a function as deprecated and inform when it has been used.
  5162  * Mark a function as deprecated and inform when it has been used.
  4725  *
  5163  *
  5825 				$display .= ' - ' . $zone['t_subcity'];
  6263 				$display .= ' - ' . $zone['t_subcity'];
  5826 			}
  6264 			}
  5827 		}
  6265 		}
  5828 
  6266 
  5829 		// Build the value.
  6267 		// Build the value.
  5830 		$value    = join( '/', $value );
  6268 		$value    = implode( '/', $value );
  5831 		$selected = '';
  6269 		$selected = '';
  5832 		if ( $value === $selected_zone ) {
  6270 		if ( $value === $selected_zone ) {
  5833 			$selected = 'selected="selected" ';
  6271 			$selected = 'selected="selected" ';
  5834 		}
  6272 		}
  5835 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . '</option>';
  6273 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . '</option>';
  5926 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . '</option>';
  6364 		$structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . '</option>';
  5927 
  6365 
  5928 	}
  6366 	}
  5929 	$structure[] = '</optgroup>';
  6367 	$structure[] = '</optgroup>';
  5930 
  6368 
  5931 	return join( "\n", $structure );
  6369 	return implode( "\n", $structure );
  5932 }
  6370 }
  5933 
  6371 
  5934 /**
  6372 /**
  5935  * Strip close comment and close php tags from file headers used by WP.
  6373  * Strip close comment and close php tags from file headers used by WP.
  5936  *
  6374  *
  6020  */
  6458  */
  6021 function get_file_data( $file, $default_headers, $context = '' ) {
  6459 function get_file_data( $file, $default_headers, $context = '' ) {
  6022 	// We don't need to write to the file, so just open for reading.
  6460 	// We don't need to write to the file, so just open for reading.
  6023 	$fp = fopen( $file, 'r' );
  6461 	$fp = fopen( $file, 'r' );
  6024 
  6462 
  6025 	// Pull only the first 8 KB of the file in.
  6463 	if ( $fp ) {
  6026 	$file_data = fread( $fp, 8 * KB_IN_BYTES );
  6464 		// Pull only the first 8 KB of the file in.
  6027 
  6465 		$file_data = fread( $fp, 8 * KB_IN_BYTES );
  6028 	// PHP will close file handle, but we are good citizens.
  6466 
  6029 	fclose( $fp );
  6467 		// PHP will close file handle, but we are good citizens.
       
  6468 		fclose( $fp );
       
  6469 	} else {
       
  6470 		$file_data = '';
       
  6471 	}
  6030 
  6472 
  6031 	// Make sure we catch CR-only line endings.
  6473 	// Make sure we catch CR-only line endings.
  6032 	$file_data = str_replace( "\r", "\n", $file_data );
  6474 	$file_data = str_replace( "\r", "\n", $file_data );
  6033 
  6475 
  6034 	/**
  6476 	/**
  6048 	} else {
  6490 	} else {
  6049 		$all_headers = $default_headers;
  6491 		$all_headers = $default_headers;
  6050 	}
  6492 	}
  6051 
  6493 
  6052 	foreach ( $all_headers as $field => $regex ) {
  6494 	foreach ( $all_headers as $field => $regex ) {
  6053 		if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) {
  6495 		if ( preg_match( '/^(?:[ \t]*<\?php)?[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) {
  6054 			$all_headers[ $field ] = _cleanup_header_comment( $match[1] );
  6496 			$all_headers[ $field ] = _cleanup_header_comment( $match[1] );
  6055 		} else {
  6497 		} else {
  6056 			$all_headers[ $field ] = '';
  6498 			$all_headers[ $field ] = '';
  6057 		}
  6499 		}
  6058 	}
  6500 	}
  6275  *
  6717  *
  6276  * @since 3.3.0
  6718  * @since 3.3.0
  6277  * @since 4.3.0 Added 'webcal' to the protocols array.
  6719  * @since 4.3.0 Added 'webcal' to the protocols array.
  6278  * @since 4.7.0 Added 'urn' to the protocols array.
  6720  * @since 4.7.0 Added 'urn' to the protocols array.
  6279  * @since 5.3.0 Added 'sms' to the protocols array.
  6721  * @since 5.3.0 Added 'sms' to the protocols array.
       
  6722  * @since 5.6.0 Added 'irc6' and 'ircs' to the protocols array.
  6280  *
  6723  *
  6281  * @see wp_kses()
  6724  * @see wp_kses()
  6282  * @see esc_url()
  6725  * @see esc_url()
  6283  *
  6726  *
  6284  * @return string[] Array of allowed protocols. Defaults to an array containing 'http', 'https',
  6727  * @return string[] Array of allowed protocols. Defaults to an array containing 'http', 'https',
  6285  *                  'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet',
  6728  *                  'ftp', 'ftps', 'mailto', 'news', 'irc', 'irc6', 'ircs', 'gopher', 'nntp', 'feed',
  6286  *                  'mms', 'rtsp', 'sms', 'svn', 'tel', 'fax', 'xmpp', 'webcal', and 'urn'.
  6729  *                  'telnet', 'mms', 'rtsp', 'sms', 'svn', 'tel', 'fax', 'xmpp', 'webcal', and 'urn'.
  6287  *                  This covers all common link protocols, except for 'javascript' which should not
  6730  *                  This covers all common link protocols, except for 'javascript' which should not
  6288  *                  be allowed for untrusted users.
  6731  *                  be allowed for untrusted users.
  6289  */
  6732  */
  6290 function wp_allowed_protocols() {
  6733 function wp_allowed_protocols() {
  6291 	static $protocols = array();
  6734 	static $protocols = array();
  6292 
  6735 
  6293 	if ( empty( $protocols ) ) {
  6736 	if ( empty( $protocols ) ) {
  6294 		$protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'sms', 'svn', 'tel', 'fax', 'xmpp', 'webcal', 'urn' );
  6737 		$protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'irc6', 'ircs', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'sms', 'svn', 'tel', 'fax', 'xmpp', 'webcal', 'urn' );
  6295 	}
  6738 	}
  6296 
  6739 
  6297 	if ( ! did_action( 'wp_loaded' ) ) {
  6740 	if ( ! did_action( 'wp_loaded' ) ) {
  6298 		/**
  6741 		/**
  6299 		 * Filters the list of protocols allowed in HTML attributes.
  6742 		 * Filters the list of protocols allowed in HTML attributes.
  6359 				$caller[] = $call['function'];
  6802 				$caller[] = $call['function'];
  6360 			}
  6803 			}
  6361 		}
  6804 		}
  6362 	}
  6805 	}
  6363 	if ( $pretty ) {
  6806 	if ( $pretty ) {
  6364 		return join( ', ', array_reverse( $caller ) );
  6807 		return implode( ', ', array_reverse( $caller ) );
  6365 	} else {
  6808 	} else {
  6366 		return $caller;
  6809 		return $caller;
  6367 	}
  6810 	}
  6368 }
  6811 }
  6369 
  6812 
  6648 function mbstring_binary_safe_encoding( $reset = false ) {
  7091 function mbstring_binary_safe_encoding( $reset = false ) {
  6649 	static $encodings  = array();
  7092 	static $encodings  = array();
  6650 	static $overloaded = null;
  7093 	static $overloaded = null;
  6651 
  7094 
  6652 	if ( is_null( $overloaded ) ) {
  7095 	if ( is_null( $overloaded ) ) {
  6653 		$overloaded = function_exists( 'mb_internal_encoding' ) && ( ini_get( 'mbstring.func_overload' ) & 2 ); // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated
  7096 		if ( function_exists( 'mb_internal_encoding' )
       
  7097 			&& ( (int) ini_get( 'mbstring.func_overload' ) & 2 ) // phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.mbstring_func_overloadDeprecated
       
  7098 		) {
       
  7099 			$overloaded = true;
       
  7100 		} else {
       
  7101 			$overloaded = false;
       
  7102 		}
  6654 	}
  7103 	}
  6655 
  7104 
  6656 	if ( false === $overloaded ) {
  7105 	if ( false === $overloaded ) {
  6657 		return;
  7106 		return;
  6658 	}
  7107 	}
  6819  *
  7268  *
  6820  * @since 4.6.0
  7269  * @since 4.6.0
  6821  *
  7270  *
  6822  * @param string $context Optional. Context in which the function is called. Accepts either 'admin',
  7271  * @param string $context Optional. Context in which the function is called. Accepts either 'admin',
  6823  *                        'image', or an arbitrary other context. If an arbitrary context is passed,
  7272  *                        'image', or an arbitrary other context. If an arbitrary context is passed,
  6824  *                        the similarly arbitrary {@see '{$context}_memory_limit'} filter will be
  7273  *                        the similarly arbitrary {@see '$context_memory_limit'} filter will be
  6825  *                        invoked. Default 'admin'.
  7274  *                        invoked. Default 'admin'.
  6826  * @return bool|int|string The limit that was set or false on failure.
  7275  * @return int|string|false The limit that was set or false on failure.
  6827  */
  7276  */
  6828 function wp_raise_memory_limit( $context = 'admin' ) {
  7277 function wp_raise_memory_limit( $context = 'admin' ) {
  6829 	// Exit early if the limit cannot be changed.
  7278 	// Exit early if the limit cannot be changed.
  6830 	if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
  7279 	if ( false === wp_is_ini_value_changeable( 'memory_limit' ) ) {
  6831 		return false;
  7280 		return false;
  7068 	 * Filters the contents of the email notification sent when the site admin email address is changed.
  7517 	 * Filters the contents of the email notification sent when the site admin email address is changed.
  7069 	 *
  7518 	 *
  7070 	 * @since 4.9.0
  7519 	 * @since 4.9.0
  7071 	 *
  7520 	 *
  7072 	 * @param array $email_change_email {
  7521 	 * @param array $email_change_email {
  7073 	 *            Used to build wp_mail().
  7522 	 *     Used to build wp_mail().
  7074 	 *
  7523 	 *
  7075 	 *            @type string $to      The intended recipient.
  7524 	 *     @type string $to      The intended recipient.
  7076 	 *            @type string $subject The subject of the email.
  7525 	 *     @type string $subject The subject of the email.
  7077 	 *            @type string $message The content of the email.
  7526 	 *     @type string $message The content of the email.
  7078 	 *                The following strings have a special meaning and will get replaced dynamically:
  7527 	 *         The following strings have a special meaning and will get replaced dynamically:
  7079 	 *                - ###OLD_EMAIL### The old site admin email address.
  7528 	 *         - ###OLD_EMAIL### The old site admin email address.
  7080 	 *                - ###NEW_EMAIL### The new site admin email address.
  7529 	 *         - ###NEW_EMAIL### The new site admin email address.
  7081 	 *                - ###SITENAME###  The name of the site.
  7530 	 *         - ###SITENAME###  The name of the site.
  7082 	 *                - ###SITEURL###   The URL to the site.
  7531 	 *         - ###SITEURL###   The URL to the site.
  7083 	 *            @type string $headers Headers.
  7532 	 *     @type string $headers Headers.
  7084 	 *        }
  7533 	 * }
  7085 	 * @param string $old_email The old site admin email address.
  7534 	 * @param string $old_email The old site admin email address.
  7086 	 * @param string $new_email The new site admin email address.
  7535 	 * @param string $new_email The new site admin email address.
  7087 	 */
  7536 	 */
  7088 	$email_change_email = apply_filters( 'site_admin_email_change_email', $email_change_email, $old_email, $new_email );
  7537 	$email_change_email = apply_filters( 'site_admin_email_change_email', $email_change_email, $old_email, $new_email );
  7089 
  7538 
  7237 
  7686 
  7238 	/**
  7687 	/**
  7239 	 * Filters the directory used to store personal data export files.
  7688 	 * Filters the directory used to store personal data export files.
  7240 	 *
  7689 	 *
  7241 	 * @since 4.9.6
  7690 	 * @since 4.9.6
       
  7691 	 * @since 5.5.0 Exports now use relative paths, so changes to the directory
       
  7692 	 *              via this filter should be reflected on the server.
  7242 	 *
  7693 	 *
  7243 	 * @param string $exports_dir Exports directory.
  7694 	 * @param string $exports_dir Exports directory.
  7244 	 */
  7695 	 */
  7245 	return apply_filters( 'wp_privacy_exports_dir', $exports_dir );
  7696 	return apply_filters( 'wp_privacy_exports_dir', $exports_dir );
  7246 }
  7697 }
  7260 
  7711 
  7261 	/**
  7712 	/**
  7262 	 * Filters the URL of the directory used to store personal data export files.
  7713 	 * Filters the URL of the directory used to store personal data export files.
  7263 	 *
  7714 	 *
  7264 	 * @since 4.9.6
  7715 	 * @since 4.9.6
       
  7716 	 * @since 5.5.0 Exports now use relative paths, so changes to the directory URL
       
  7717 	 *              via this filter should be reflected on the server.
  7265 	 *
  7718 	 *
  7266 	 * @param string $exports_url Exports directory URL.
  7719 	 * @param string $exports_url Exports directory URL.
  7267 	 */
  7720 	 */
  7268 	return apply_filters( 'wp_privacy_exports_url', $exports_url );
  7721 	return apply_filters( 'wp_privacy_exports_url', $exports_url );
  7269 }
  7722 }
  7299 	if ( ! is_dir( $exports_dir ) ) {
  7752 	if ( ! is_dir( $exports_dir ) ) {
  7300 		return;
  7753 		return;
  7301 	}
  7754 	}
  7302 
  7755 
  7303 	require_once ABSPATH . 'wp-admin/includes/file.php';
  7756 	require_once ABSPATH . 'wp-admin/includes/file.php';
  7304 	$export_files = list_files( $exports_dir, 100, array( 'index.html' ) );
  7757 	$export_files = list_files( $exports_dir, 100, array( 'index.php' ) );
  7305 
  7758 
  7306 	/**
  7759 	/**
  7307 	 * Filters the lifetime, in seconds, of a personal data export file.
  7760 	 * Filters the lifetime, in seconds, of a personal data export file.
  7308 	 *
  7761 	 *
  7309 	 * By default, the lifetime is 3 days. Once the file reaches that age, it will automatically
  7762 	 * By default, the lifetime is 3 days. Once the file reaches that age, it will automatically
  7472 		return;
  7925 		return;
  7473 	}
  7926 	}
  7474 
  7927 
  7475 	echo '<p class="button-container">';
  7928 	echo '<p class="button-container">';
  7476 	printf(
  7929 	printf(
  7477 		'<a class="button button-primary" href="%1$s" target="_blank" rel="noopener noreferrer">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
  7930 		'<a class="button button-primary" href="%1$s" target="_blank" rel="noopener">%2$s <span class="screen-reader-text">%3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
  7478 		esc_url( $direct_update_url ),
  7931 		esc_url( $direct_update_url ),
  7479 		__( 'Update PHP' ),
  7932 		__( 'Update PHP' ),
  7480 		/* translators: Accessibility text. */
  7933 		/* translators: Accessibility text. */
  7481 		__( '(opens in a new tab)' )
  7934 		__( '(opens in a new tab)' )
  7482 	);
  7935 	);
  7483 	echo '</p>';
  7936 	echo '</p>';
  7484 }
  7937 }
  7485 
  7938 
  7486 /**
  7939 /**
       
  7940  * Gets the URL to learn more about updating the site to use HTTPS.
       
  7941  *
       
  7942  * This URL can be overridden by specifying an environment variable `WP_UPDATE_HTTPS_URL` or by using the
       
  7943  * {@see 'wp_update_https_url'} filter. Providing an empty string is not allowed and will result in the
       
  7944  * default URL being used. Furthermore the page the URL links to should preferably be localized in the
       
  7945  * site language.
       
  7946  *
       
  7947  * @since 5.7.0
       
  7948  *
       
  7949  * @return string URL to learn more about updating to HTTPS.
       
  7950  */
       
  7951 function wp_get_update_https_url() {
       
  7952 	$default_url = wp_get_default_update_https_url();
       
  7953 
       
  7954 	$update_url = $default_url;
       
  7955 	if ( false !== getenv( 'WP_UPDATE_HTTPS_URL' ) ) {
       
  7956 		$update_url = getenv( 'WP_UPDATE_HTTPS_URL' );
       
  7957 	}
       
  7958 
       
  7959 	/**
       
  7960 	 * Filters the URL to learn more about updating the HTTPS version the site is running on.
       
  7961 	 *
       
  7962 	 * Providing an empty string is not allowed and will result in the default URL being used. Furthermore
       
  7963 	 * the page the URL links to should preferably be localized in the site language.
       
  7964 	 *
       
  7965 	 * @since 5.7.0
       
  7966 	 *
       
  7967 	 * @param string $update_url URL to learn more about updating HTTPS.
       
  7968 	 */
       
  7969 	$update_url = apply_filters( 'wp_update_https_url', $update_url );
       
  7970 	if ( empty( $update_url ) ) {
       
  7971 		$update_url = $default_url;
       
  7972 	}
       
  7973 
       
  7974 	return $update_url;
       
  7975 }
       
  7976 
       
  7977 /**
       
  7978  * Gets the default URL to learn more about updating the site to use HTTPS.
       
  7979  *
       
  7980  * Do not use this function to retrieve this URL. Instead, use {@see wp_get_update_https_url()} when relying on the URL.
       
  7981  * This function does not allow modifying the returned URL, and is only used to compare the actually used URL with the
       
  7982  * default one.
       
  7983  *
       
  7984  * @since 5.7.0
       
  7985  * @access private
       
  7986  *
       
  7987  * @return string Default URL to learn more about updating to HTTPS.
       
  7988  */
       
  7989 function wp_get_default_update_https_url() {
       
  7990 	/* translators: Documentation explaining HTTPS and why it should be used. */
       
  7991 	return __( 'https://wordpress.org/support/article/why-should-i-use-https/' );
       
  7992 }
       
  7993 
       
  7994 /**
       
  7995  * Gets the URL for directly updating the site to use HTTPS.
       
  7996  *
       
  7997  * A URL will only be returned if the `WP_DIRECT_UPDATE_HTTPS_URL` environment variable is specified or
       
  7998  * by using the {@see 'wp_direct_update_https_url'} filter. This allows hosts to send users directly to
       
  7999  * the page where they can update their site to use HTTPS.
       
  8000  *
       
  8001  * @since 5.7.0
       
  8002  *
       
  8003  * @return string URL for directly updating to HTTPS or empty string.
       
  8004  */
       
  8005 function wp_get_direct_update_https_url() {
       
  8006 	$direct_update_url = '';
       
  8007 
       
  8008 	if ( false !== getenv( 'WP_DIRECT_UPDATE_HTTPS_URL' ) ) {
       
  8009 		$direct_update_url = getenv( 'WP_DIRECT_UPDATE_HTTPS_URL' );
       
  8010 	}
       
  8011 
       
  8012 	/**
       
  8013 	 * Filters the URL for directly updating the PHP version the site is running on from the host.
       
  8014 	 *
       
  8015 	 * @since 5.7.0
       
  8016 	 *
       
  8017 	 * @param string $direct_update_url URL for directly updating PHP.
       
  8018 	 */
       
  8019 	$direct_update_url = apply_filters( 'wp_direct_update_https_url', $direct_update_url );
       
  8020 
       
  8021 	return $direct_update_url;
       
  8022 }
       
  8023 
       
  8024 /**
  7487  * Get the size of a directory.
  8025  * Get the size of a directory.
  7488  *
  8026  *
  7489  * A helper function that is used primarily to check whether
  8027  * A helper function that is used primarily to check whether
  7490  * a blog has exceeded its allowed upload space.
  8028  * a blog has exceeded its allowed upload space.
  7491  *
  8029  *
  7496  * @param int    $max_execution_time Maximum time to run before giving up. In seconds.
  8034  * @param int    $max_execution_time Maximum time to run before giving up. In seconds.
  7497  *                                   The timeout is global and is measured from the moment WordPress started to load.
  8035  *                                   The timeout is global and is measured from the moment WordPress started to load.
  7498  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  8036  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  7499  */
  8037  */
  7500 function get_dirsize( $directory, $max_execution_time = null ) {
  8038 function get_dirsize( $directory, $max_execution_time = null ) {
  7501 	$dirsize = get_transient( 'dirsize_cache' );
       
  7502 
       
  7503 	if ( is_array( $dirsize ) && isset( $dirsize[ $directory ]['size'] ) ) {
       
  7504 		return $dirsize[ $directory ]['size'];
       
  7505 	}
       
  7506 
       
  7507 	if ( ! is_array( $dirsize ) ) {
       
  7508 		$dirsize = array();
       
  7509 	}
       
  7510 
  8039 
  7511 	// Exclude individual site directories from the total when checking the main site of a network,
  8040 	// Exclude individual site directories from the total when checking the main site of a network,
  7512 	// as they are subdirectories and should not be counted.
  8041 	// as they are subdirectories and should not be counted.
  7513 	if ( is_multisite() && is_main_site() ) {
  8042 	if ( is_multisite() && is_main_site() ) {
  7514 		$dirsize[ $directory ]['size'] = recurse_dirsize( $directory, $directory . '/sites', $max_execution_time );
  8043 		$size = recurse_dirsize( $directory, $directory . '/sites', $max_execution_time );
  7515 	} else {
  8044 	} else {
  7516 		$dirsize[ $directory ]['size'] = recurse_dirsize( $directory, null, $max_execution_time );
  8045 		$size = recurse_dirsize( $directory, null, $max_execution_time );
  7517 	}
  8046 	}
  7518 
  8047 
  7519 	set_transient( 'dirsize_cache', $dirsize, HOUR_IN_SECONDS );
  8048 	return $size;
  7520 	return $dirsize[ $directory ]['size'];
       
  7521 }
  8049 }
  7522 
  8050 
  7523 /**
  8051 /**
  7524  * Get the size of a directory recursively.
  8052  * Get the size of a directory recursively.
  7525  *
  8053  *
  7526  * Used by get_dirsize() to get a directory's size when it contains
  8054  * Used by get_dirsize() to get a directory size when it contains other directories.
  7527  * other directories.
       
  7528  *
  8055  *
  7529  * @since MU (3.0.0)
  8056  * @since MU (3.0.0)
  7530  * @since 4.3.0 $exclude parameter added.
  8057  * @since 4.3.0 The `$exclude` parameter was added.
  7531  * @since 5.2.0 $max_execution_time parameter added.
  8058  * @since 5.2.0 The `$max_execution_time` parameter was added.
       
  8059  * @since 5.6.0 The `$directory_cache` parameter was added.
  7532  *
  8060  *
  7533  * @param string       $directory          Full path of a directory.
  8061  * @param string       $directory          Full path of a directory.
  7534  * @param string|array $exclude            Optional. Full path of a subdirectory to exclude from the total,
  8062  * @param string|array $exclude            Optional. Full path of a subdirectory to exclude from the total,
  7535  *                                         or array of paths. Expected without trailing slash(es).
  8063  *                                         or array of paths. Expected without trailing slash(es).
  7536  * @param int          $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global
  8064  * @param int          $max_execution_time Maximum time to run before giving up. In seconds. The timeout is global
  7537  *                                         and is measured from the moment WordPress started to load.
  8065  *                                         and is measured from the moment WordPress started to load.
       
  8066  * @param array        $directory_cache    Optional. Array of cached directory paths.
       
  8067  *
  7538  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  8068  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  7539  */
  8069  */
  7540 function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null ) {
  8070 function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null, &$directory_cache = null ) {
  7541 	$size = 0;
  8071 	$directory  = untrailingslashit( $directory );
  7542 
  8072 	$save_cache = false;
  7543 	$directory = untrailingslashit( $directory );
  8073 
       
  8074 	if ( ! isset( $directory_cache ) ) {
       
  8075 		$directory_cache = get_transient( 'dirsize_cache' );
       
  8076 		$save_cache      = true;
       
  8077 	}
       
  8078 
       
  8079 	if ( isset( $directory_cache[ $directory ] ) && is_int( $directory_cache[ $directory ] ) ) {
       
  8080 		return $directory_cache[ $directory ];
       
  8081 	}
  7544 
  8082 
  7545 	if ( ! file_exists( $directory ) || ! is_dir( $directory ) || ! is_readable( $directory ) ) {
  8083 	if ( ! file_exists( $directory ) || ! is_dir( $directory ) || ! is_readable( $directory ) ) {
  7546 		return false;
  8084 		return false;
  7547 	}
  8085 	}
  7548 
  8086 
  7566 		if ( $max_execution_time > 10 ) {
  8104 		if ( $max_execution_time > 10 ) {
  7567 			$max_execution_time -= 1;
  8105 			$max_execution_time -= 1;
  7568 		}
  8106 		}
  7569 	}
  8107 	}
  7570 
  8108 
  7571 	$handle = opendir( $directory );
  8109 	/**
  7572 	if ( $handle ) {
  8110 	 * Filters the amount of storage space used by one directory and all its children, in megabytes.
  7573 		while ( ( $file = readdir( $handle ) ) !== false ) {
  8111 	 *
  7574 			$path = $directory . '/' . $file;
  8112 	 * Return the actual used space to short-circuit the recursive PHP file size calculation
  7575 			if ( '.' !== $file && '..' !== $file ) {
  8113 	 * and use something else, like a CDN API or native operating system tools for better performance.
  7576 				if ( is_file( $path ) ) {
  8114 	 *
  7577 					$size += filesize( $path );
  8115 	 * @since 5.6.0
  7578 				} elseif ( is_dir( $path ) ) {
  8116 	 *
  7579 					$handlesize = recurse_dirsize( $path, $exclude, $max_execution_time );
  8117 	 * @param int|false $space_used The amount of used space, in bytes. Default false.
  7580 					if ( $handlesize > 0 ) {
  8118 	 */
  7581 						$size += $handlesize;
  8119 	$size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache );
       
  8120 
       
  8121 	if ( false === $size ) {
       
  8122 		$size = 0;
       
  8123 
       
  8124 		$handle = opendir( $directory );
       
  8125 		if ( $handle ) {
       
  8126 			while ( ( $file = readdir( $handle ) ) !== false ) {
       
  8127 				$path = $directory . '/' . $file;
       
  8128 				if ( '.' !== $file && '..' !== $file ) {
       
  8129 					if ( is_file( $path ) ) {
       
  8130 						$size += filesize( $path );
       
  8131 					} elseif ( is_dir( $path ) ) {
       
  8132 						$handlesize = recurse_dirsize( $path, $exclude, $max_execution_time, $directory_cache );
       
  8133 						if ( $handlesize > 0 ) {
       
  8134 							$size += $handlesize;
       
  8135 						}
       
  8136 					}
       
  8137 
       
  8138 					if ( $max_execution_time > 0 && microtime( true ) - WP_START_TIMESTAMP > $max_execution_time ) {
       
  8139 						// Time exceeded. Give up instead of risking a fatal timeout.
       
  8140 						$size = null;
       
  8141 						break;
  7582 					}
  8142 					}
  7583 				}
  8143 				}
  7584 
       
  7585 				if ( $max_execution_time > 0 && microtime( true ) - WP_START_TIMESTAMP > $max_execution_time ) {
       
  7586 					// Time exceeded. Give up instead of risking a fatal timeout.
       
  7587 					$size = null;
       
  7588 					break;
       
  7589 				}
       
  7590 			}
  8144 			}
  7591 		}
  8145 			closedir( $handle );
  7592 		closedir( $handle );
  8146 		}
  7593 	}
  8147 	}
       
  8148 
       
  8149 	$directory_cache[ $directory ] = $size;
       
  8150 
       
  8151 	// Only write the transient on the top level call and not on recursive calls.
       
  8152 	if ( $save_cache ) {
       
  8153 		set_transient( 'dirsize_cache', $directory_cache );
       
  8154 	}
       
  8155 
  7594 	return $size;
  8156 	return $size;
       
  8157 }
       
  8158 
       
  8159 /**
       
  8160  * Cleans directory size cache used by recurse_dirsize().
       
  8161  *
       
  8162  * Removes the current directory and all parent directories from the `dirsize_cache` transient.
       
  8163  *
       
  8164  * @since 5.6.0
       
  8165  *
       
  8166  * @param string $path Full path of a directory or file.
       
  8167  */
       
  8168 function clean_dirsize_cache( $path ) {
       
  8169 	$directory_cache = get_transient( 'dirsize_cache' );
       
  8170 
       
  8171 	if ( empty( $directory_cache ) ) {
       
  8172 		return;
       
  8173 	}
       
  8174 
       
  8175 	$path = untrailingslashit( $path );
       
  8176 	unset( $directory_cache[ $path ] );
       
  8177 
       
  8178 	while ( DIRECTORY_SEPARATOR !== $path && '.' !== $path && '..' !== $path ) {
       
  8179 		$path = dirname( $path );
       
  8180 		unset( $directory_cache[ $path ] );
       
  8181 	}
       
  8182 
       
  8183 	set_transient( 'dirsize_cache', $directory_cache );
  7595 }
  8184 }
  7596 
  8185 
  7597 /**
  8186 /**
  7598  * Checks compatibility with the current WordPress version.
  8187  * Checks compatibility with the current WordPress version.
  7599  *
  8188  *