wp/wp-includes/functions.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
--- a/wp/wp-includes/functions.php	Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-includes/functions.php	Fri Sep 05 18:40:08 2025 +0200
@@ -8,7 +8,7 @@
 require ABSPATH . WPINC . '/option.php';
 
 /**
- * Convert given MySQL date string into a different format.
+ * Converts given MySQL date string into a different format.
  *
  *  - `$format` should be a PHP date format string.
  *  - 'U' and 'G' formats will return an integer sum of timestamp with timezone offset.
@@ -32,7 +32,8 @@
 		return false;
 	}
 
-	$datetime = date_create( $date, wp_timezone() );
+	$timezone = wp_timezone();
+	$datetime = date_create( $date, $timezone );
 
 	if ( false === $datetime ) {
 		return false;
@@ -44,7 +45,7 @@
 	}
 
 	if ( $translate ) {
-		return wp_date( $format, $datetime->getTimestamp() );
+		return wp_date( $format, $datetime->getTimestamp(), $timezone );
 	}
 
 	return $datetime->format( $format );
@@ -163,8 +164,6 @@
  * @since 0.71
  * @since 5.3.0 Converted into a wrapper for wp_date().
  *
- * @global WP_Locale $wp_locale WordPress date and time locale object.
- *
  * @param string   $format                Format to display the date.
  * @param int|bool $timestamp_with_offset Optional. A sum of Unix timestamp and timezone offset
  *                                        in seconds. Default false.
@@ -264,7 +263,7 @@
 		$month         = $wp_locale->get_month( $datetime->format( 'm' ) );
 		$weekday       = $wp_locale->get_weekday( $datetime->format( 'w' ) );
 
-		for ( $i = 0; $i < $format_length; $i ++ ) {
+		for ( $i = 0; $i < $format_length; $i++ ) {
 			switch ( $format[ $i ] ) {
 				case 'D':
 					$new_format .= addcslashes( $wp_locale->get_weekday_abbrev( $weekday ), '\\A..Za..z' );
@@ -408,7 +407,7 @@
 }
 
 /**
- * Convert float number to format based on the locale.
+ * Converts float number to format based on the locale.
  *
  * @since 2.3.0
  *
@@ -498,7 +497,7 @@
 }
 
 /**
- * Convert a duration to human readable format.
+ * Converts a duration to human readable format.
  *
  * @since 5.1.0
  *
@@ -514,7 +513,7 @@
 	$duration = trim( $duration );
 
 	// Remove prepended negative sign.
-	if ( '-' === substr( $duration, 0, 1 ) ) {
+	if ( str_starts_with( $duration, '-' ) ) {
 		$duration = substr( $duration, 1 );
 	}
 
@@ -568,7 +567,7 @@
 }
 
 /**
- * Get the week start and end from the datetime or date string from MySQL.
+ * Gets the week start and end from the datetime or date string from MySQL.
  *
  * @since 0.71
  *
@@ -614,7 +613,7 @@
 }
 
 /**
- * Serialize data, if needed.
+ * Serializes data, if needed.
  *
  * @since 2.0.5
  *
@@ -639,7 +638,7 @@
 }
 
 /**
- * Unserialize data only if it was serialized.
+ * Unserializes data only if it was serialized.
  *
  * @since 2.0.0
  *
@@ -655,12 +654,13 @@
 }
 
 /**
- * Check value to find if it was serialized.
- *
- * If $data is not an string, then returned value will always be false.
+ * Checks value to find if it was serialized.
+ *
+ * If $data is not a string, then returned value will always be false.
  * Serialized data is always a string.
  *
  * @since 2.0.5
+ * @since 6.1.0 Added Enum support.
  *
  * @param string $data   Value to check to see if was serialized.
  * @param bool   $strict Optional. Whether to be strict about the end of the string. Default true.
@@ -708,12 +708,13 @@
 				if ( '"' !== substr( $data, -2, 1 ) ) {
 					return false;
 				}
-			} elseif ( false === strpos( $data, '"' ) ) {
+			} elseif ( ! str_contains( $data, '"' ) ) {
 				return false;
 			}
 			// Or else fall through.
 		case 'a':
 		case 'O':
+		case 'E':
 			return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
 		case 'b':
 		case 'i':
@@ -725,7 +726,7 @@
 }
 
 /**
- * Check whether serialized data is of string type.
+ * Checks whether serialized data is of string type.
  *
  * @since 2.0.5
  *
@@ -742,7 +743,7 @@
 		return false;
 	} elseif ( ':' !== $data[1] ) {
 		return false;
-	} elseif ( ';' !== substr( $data, -1 ) ) {
+	} elseif ( ! str_ends_with( $data, ';' ) ) {
 		return false;
 	} elseif ( 's' !== $data[0] ) {
 		return false;
@@ -754,7 +755,7 @@
 }
 
 /**
- * Retrieve post title from XMLRPC XML.
+ * Retrieves post title from XMLRPC XML.
  *
  * If the title element is not part of the XML, then the default post title from
  * the $post_default_title will be used instead.
@@ -777,7 +778,7 @@
 }
 
 /**
- * Retrieve the post category or categories from XMLRPC XML.
+ * Retrieves the post category or categories from XMLRPC XML.
  *
  * If the category element is not found, then the default post category will be
  * used. The return type then would be what $post_default_category. If the
@@ -817,7 +818,7 @@
 }
 
 /**
- * Use RegEx to extract URLs from arbitrary content.
+ * Uses RegEx to extract URLs from arbitrary content.
  *
  * @since 3.7.0
  * @since 6.0.0 Fixes support for HTML entities (Trac 30580).
@@ -845,7 +846,7 @@
 
 	$post_links = array_unique(
 		array_map(
-			static function( $link ) {
+			static function ( $link ) {
 				// Decode to replace valid entities, like &amp;.
 				$link = html_entity_decode( $link );
 				// Maintain backward compatibility by removing extraneous semi-colons (`;`).
@@ -859,7 +860,7 @@
 }
 
 /**
- * Check content for video and audio links to add as enclosures.
+ * Checks content for video and audio links to add as enclosures.
  *
  * Will not add enclosures that have already been added and will
  * remove enclosures that are no longer in the post. This is called as
@@ -881,7 +882,7 @@
 	global $wpdb;
 
 	// @todo Tidy this code and make the debug code optional.
-	include_once ABSPATH . WPINC . '/class-IXR.php';
+	require_once ABSPATH . WPINC . '/class-IXR.php';
 
 	$post = get_post( $post );
 	if ( ! $post ) {
@@ -932,7 +933,7 @@
 	 * @since 4.4.0
 	 *
 	 * @param string[] $post_links An array of enclosure links.
-	 * @param int      $post_ID    Post ID.
+	 * @param int      $post_id    Post ID.
 	 */
 	$post_links = apply_filters( 'enclosure_links', $post_links, $post->ID );
 
@@ -943,8 +944,8 @@
 
 			$headers = wp_get_http_headers( $url );
 			if ( $headers ) {
-				$len           = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
-				$type          = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
+				$len           = isset( $headers['Content-Length'] ) ? (int) $headers['Content-Length'] : 0;
+				$type          = isset( $headers['Content-Type'] ) ? $headers['Content-Type'] : '';
 				$allowed_types = array( 'video', 'audio' );
 
 				// Check to see if we can figure out the mime type from the extension.
@@ -970,13 +971,13 @@
 }
 
 /**
- * Retrieve HTTP Headers from URL.
+ * Retrieves HTTP Headers from URL.
  *
  * @since 1.5.1
  *
  * @param string $url        URL to retrieve HTTP headers from.
  * @param bool   $deprecated Not Used.
- * @return string|false Headers on success, false on failure.
+ * @return \WpOrg\Requests\Utility\CaseInsensitiveDictionary|false Headers on success, false on failure.
  */
 function wp_get_http_headers( $url, $deprecated = false ) {
 	if ( ! empty( $deprecated ) ) {
@@ -1018,7 +1019,7 @@
 }
 
 /**
- * Build URL query based on an associative and, or indexed array.
+ * Builds URL query based on an associative and, or indexed array.
  *
  * This is a convenient function for easily building url queries. It sets the
  * separator to '&' and uses _http_build_query() function.
@@ -1049,7 +1050,7 @@
  *                                Default null.
  * @param string       $sep       Optional. Argument separator; defaults to 'arg_separator.output'.
  *                                Default null.
- * @param string       $key       Optional. Used to prefix key name. Default empty.
+ * @param string       $key       Optional. Used to prefix key name. Default empty string.
  * @param bool         $urlencode Optional. Whether to use urlencode() in the result. Default true.
  * @return string The query string.
  */
@@ -1060,12 +1061,15 @@
 		if ( $urlencode ) {
 			$k = urlencode( $k );
 		}
-		if ( is_int( $k ) && null != $prefix ) {
+
+		if ( is_int( $k ) && null !== $prefix ) {
 			$k = $prefix . $k;
 		}
+
 		if ( ! empty( $key ) ) {
 			$k = $key . '%5B' . $k . '%5D';
 		}
+
 		if ( null === $v ) {
 			continue;
 		} elseif ( false === $v ) {
@@ -1157,10 +1161,10 @@
 		$protocol = '';
 	}
 
-	if ( strpos( $uri, '?' ) !== false ) {
+	if ( str_contains( $uri, '?' ) ) {
 		list( $base, $query ) = explode( '?', $uri, 2 );
 		$base                .= '?';
-	} elseif ( $protocol || strpos( $uri, '=' ) === false ) {
+	} elseif ( $protocol || ! str_contains( $uri, '=' ) ) {
 		$base  = $uri . '?';
 		$query = '';
 	} else {
@@ -1196,6 +1200,10 @@
 /**
  * Removes an item or items from a query string.
  *
+ * Important: The return value of remove_query_arg() is not escaped by default. Output should be
+ * late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting
+ * (XSS) attacks.
+ *
  * @since 1.5.0
  *
  * @param string|string[] $key   Query key or keys to remove.
@@ -1267,21 +1275,19 @@
  * @since 0.71
  * @since 5.5.0 Non-string values are left untouched.
  *
- * @param array $array Array to walk while sanitizing contents.
- * @return array Sanitized $array.
- */
-function add_magic_quotes( $array ) {
-	foreach ( (array) $array as $k => $v ) {
+ * @param array $input_array Array to walk while sanitizing contents.
+ * @return array Sanitized $input_array.
+ */
+function add_magic_quotes( $input_array ) {
+	foreach ( (array) $input_array as $k => $v ) {
 		if ( is_array( $v ) ) {
-			$array[ $k ] = add_magic_quotes( $v );
+			$input_array[ $k ] = add_magic_quotes( $v );
 		} elseif ( is_string( $v ) ) {
-			$array[ $k ] = addslashes( $v );
-		} else {
-			continue;
-		}
-	}
-
-	return $array;
+			$input_array[ $k ] = addslashes( $v );
+		}
+	}
+
+	return $input_array;
 }
 
 /**
@@ -1314,7 +1320,7 @@
 }
 
 /**
- * Set up the WordPress query.
+ * Sets up the WordPress query.
  *
  * @since 2.0.0
  *
@@ -1335,12 +1341,13 @@
 }
 
 /**
- * Retrieve the description for the HTTP status.
+ * Retrieves the description for the HTTP status.
  *
  * @since 2.3.0
  * @since 3.9.0 Added status codes 418, 428, 429, 431, and 511.
  * @since 4.5.0 Added status codes 308, 421, and 451.
  * @since 5.1.0 Added status code 103.
+ * @since 6.6.0 Added status code 425.
  *
  * @global array $wp_header_to_desc
  *
@@ -1402,6 +1409,7 @@
 			422 => 'Unprocessable Entity',
 			423 => 'Locked',
 			424 => 'Failed Dependency',
+			425 => 'Too Early',
 			426 => 'Upgrade Required',
 			428 => 'Precondition Required',
 			429 => 'Too Many Requests',
@@ -1429,7 +1437,7 @@
 }
 
 /**
- * Set HTTP status header.
+ * Sets HTTP status header.
  *
  * @since 2.0.0
  * @since 4.4.0 Added the `$description` parameter.
@@ -1438,6 +1446,7 @@
  *
  * @param int    $code        HTTP status code.
  * @param string $description Optional. A custom description for the HTTP status.
+ *                            Defaults to the result of get_status_header_desc() for the given code.
  */
 function status_header( $code, $description = '' ) {
 	if ( ! $description ) {
@@ -1471,35 +1480,36 @@
 }
 
 /**
- * Get the header information to prevent caching.
+ * Gets the HTTP header information to prevent caching.
  *
  * The several different headers cover the different ways cache prevention
- * is handled by different browsers
+ * is handled by different browsers.
  *
  * @since 2.8.0
+ * @since 6.3.0 The `Cache-Control` header for logged in users now includes the
+ *              `no-store` and `private` directives.
  *
  * @return array The associative array of header names and field values.
  */
 function wp_get_nocache_headers() {
+	$cache_control = ( function_exists( 'is_user_logged_in' ) && is_user_logged_in() )
+		? 'no-cache, must-revalidate, max-age=0, no-store, private'
+		: 'no-cache, must-revalidate, max-age=0';
+
 	$headers = array(
 		'Expires'       => 'Wed, 11 Jan 1984 05:00:00 GMT',
-		'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
+		'Cache-Control' => $cache_control,
 	);
 
 	if ( function_exists( 'apply_filters' ) ) {
 		/**
-		 * Filters the cache-controlling headers.
+		 * Filters the cache-controlling HTTP headers that are used to prevent caching.
 		 *
 		 * @since 2.8.0
 		 *
 		 * @see wp_get_nocache_headers()
 		 *
-		 * @param array $headers {
-		 *     Header names and field values.
-		 *
-		 *     @type string $Expires       Expires header.
-		 *     @type string $Cache-Control Cache-Control header.
-		 * }
+		 * @param array $headers Header names and field values.
 		 */
 		$headers = (array) apply_filters( 'nocache_headers', $headers );
 	}
@@ -1508,7 +1518,7 @@
 }
 
 /**
- * Set the headers to prevent caching for the different browsers.
+ * Sets the HTTP headers to prevent caching for the different browsers.
  *
  * Different browsers support different nocache headers, so several
  * headers must be sent so that all of them get the point that no
@@ -1535,20 +1545,20 @@
 }
 
 /**
- * Set the headers for caching for 10 days with JavaScript content type.
+ * Sets the HTTP headers for caching for 10 days with JavaScript content type.
  *
  * @since 2.1.0
  */
 function cache_javascript_headers() {
-	$expiresOffset = 10 * DAY_IN_SECONDS;
+	$expires_offset = 10 * DAY_IN_SECONDS;
 
 	header( 'Content-Type: text/javascript; charset=' . get_bloginfo( 'charset' ) );
 	header( 'Vary: Accept-Encoding' ); // Handle proxies.
-	header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + $expiresOffset ) . ' GMT' );
-}
-
-/**
- * Retrieve the number of database queries during the WordPress execution.
+	header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + $expires_offset ) . ' GMT' );
+}
+
+/**
+ * Retrieves the number of database queries during the WordPress execution.
  *
  * @since 2.0.0
  *
@@ -1562,7 +1572,7 @@
 }
 
 /**
- * Whether input is yes or no.
+ * Determines whether input is yes or no.
  *
  * Must be 'y' to be true.
  *
@@ -1576,7 +1586,7 @@
 }
 
 /**
- * Load the feed template from the use of an action hook.
+ * Loads the feed template from the use of an action hook.
  *
  * If the feed action does not have a hook, then the function will die with a
  * message telling the visitor that the feed is not valid.
@@ -1600,7 +1610,7 @@
 	}
 
 	if ( ! has_action( "do_feed_{$feed}" ) ) {
-		wp_die( __( '<strong>Error</strong>: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
+		wp_die( __( '<strong>Error:</strong> This is not a valid feed template.' ), '', array( 'response' => 404 ) );
 	}
 
 	/**
@@ -1625,7 +1635,7 @@
 }
 
 /**
- * Load the RDF RSS 0.91 Feed template.
+ * Loads the RDF RSS 0.91 Feed template.
  *
  * @since 2.1.0
  *
@@ -1636,7 +1646,7 @@
 }
 
 /**
- * Load the RSS 1.0 Feed Template.
+ * Loads the RSS 1.0 Feed Template.
  *
  * @since 2.1.0
  *
@@ -1647,7 +1657,7 @@
 }
 
 /**
- * Load either the RSS2 comment feed or the RSS2 posts feed.
+ * Loads either the RSS2 comment feed or the RSS2 posts feed.
  *
  * @since 2.1.0
  *
@@ -1664,7 +1674,7 @@
 }
 
 /**
- * Load either Atom comment feed or Atom posts feed.
+ * Loads either Atom comment feed or Atom posts feed.
  *
  * @since 2.1.0
  *
@@ -1684,7 +1694,7 @@
  * Displays the default robots.txt file content.
  *
  * @since 2.1.0
- * @since 5.3.0 Remove the "Disallow: /" output if search engine visiblity is
+ * @since 5.3.0 Remove the "Disallow: /" output if search engine visibility is
  *              discouraged in favor of robots meta HTML tag via wp_robots_no_robots()
  *              filter callback.
  */
@@ -1718,7 +1728,7 @@
 }
 
 /**
- * Display the favicon.ico file content.
+ * Displays the favicon.ico file content.
  *
  * @since 5.4.0
  */
@@ -1765,15 +1775,18 @@
 	}
 
 	$suppress = $wpdb->suppress_errors();
+
 	if ( ! wp_installing() ) {
 		$alloptions = wp_load_alloptions();
 	}
+
 	// If siteurl is not set to autoload, check it specifically.
 	if ( ! isset( $alloptions['siteurl'] ) ) {
 		$installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
 	} else {
 		$installed = $alloptions['siteurl'];
 	}
+
 	$wpdb->suppress_errors( $suppress );
 
 	$installed = ! empty( $installed );
@@ -1798,10 +1811,11 @@
 	$wp_tables = $wpdb->tables();
 	foreach ( $wp_tables as $table ) {
 		// The existence of custom user tables shouldn't suggest an unwise state or prevent a clean installation.
-		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table ) {
+		if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE === $table ) {
 			continue;
 		}
-		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table ) {
+
+		if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE === $table ) {
 			continue;
 		}
 
@@ -1835,7 +1849,7 @@
 }
 
 /**
- * Retrieve URL with nonce added to URL query.
+ * Retrieves URL with nonce added to URL query.
  *
  * @since 2.0.4
  *
@@ -1850,7 +1864,7 @@
 }
 
 /**
- * Retrieve or display nonce hidden field for forms.
+ * Retrieves or display nonce hidden field for forms.
  *
  * The nonce field is used to validate that the contents of the form came from
  * the location on the current site and not somewhere else. The nonce does not
@@ -1872,10 +1886,10 @@
  * @param int|string $action  Optional. Action name. Default -1.
  * @param string     $name    Optional. Nonce name. Default '_wpnonce'.
  * @param bool       $referer Optional. Whether to set the referer field for validation. Default true.
- * @param bool       $echo    Optional. Whether to display or return hidden form field. Default true.
+ * @param bool       $display Optional. Whether to display or return hidden form field. Default true.
  * @return string Nonce field HTML markup.
  */
-function wp_nonce_field( $action = -1, $name = '_wpnonce', $referer = true, $echo = true ) {
+function wp_nonce_field( $action = -1, $name = '_wpnonce', $referer = true, $display = true ) {
 	$name        = esc_attr( $name );
 	$nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
 
@@ -1883,7 +1897,7 @@
 		$nonce_field .= wp_referer_field( false );
 	}
 
-	if ( $echo ) {
+	if ( $display ) {
 		echo $nonce_field;
 	}
 
@@ -1891,20 +1905,21 @@
 }
 
 /**
- * Retrieve or display referer hidden field for forms.
+ * Retrieves or displays referer hidden field for forms.
  *
  * The referer link is the current Request URI from the server super global. The
  * input name is '_wp_http_referer', in case you wanted to check manually.
  *
  * @since 2.0.4
  *
- * @param bool $echo Optional. Whether to echo or return the referer field. Default true.
+ * @param bool $display Optional. Whether to echo or return the referer field. Default true.
  * @return string Referer field HTML markup.
  */
-function wp_referer_field( $echo = true ) {
-	$referer_field = '<input type="hidden" name="_wp_http_referer" value="' . esc_attr( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . '" />';
-
-	if ( $echo ) {
+function wp_referer_field( $display = true ) {
+	$request_url   = remove_query_arg( '_wp_http_referer' );
+	$referer_field = '<input type="hidden" name="_wp_http_referer" value="' . esc_url( $request_url ) . '" />';
+
+	if ( $display ) {
 		echo $referer_field;
 	}
 
@@ -1912,7 +1927,7 @@
 }
 
 /**
- * Retrieve or display original referer hidden field for forms.
+ * Retrieves or displays original referer hidden field for forms.
  *
  * The input name is '_wp_original_http_referer' and will be either the same
  * value of wp_referer_field(), if that was posted already or it will be the
@@ -1920,12 +1935,12 @@
  *
  * @since 2.0.4
  *
- * @param bool   $echo         Optional. Whether to echo the original http referer. Default true.
+ * @param bool   $display      Optional. Whether to echo the original http referer. Default true.
  * @param string $jump_back_to Optional. Can be 'previous' or page you want to jump back to.
  *                             Default 'current'.
  * @return string Original referer field.
  */
-function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
+function wp_original_referer_field( $display = true, $jump_back_to = 'current' ) {
 	$ref = wp_get_original_referer();
 
 	if ( ! $ref ) {
@@ -1934,7 +1949,7 @@
 
 	$orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( $ref ) . '" />';
 
-	if ( $echo ) {
+	if ( $display ) {
 		echo $orig_referer_field;
 	}
 
@@ -1942,7 +1957,7 @@
 }
 
 /**
- * Retrieve referer from '_wp_http_referer' or HTTP referer.
+ * Retrieves referer from '_wp_http_referer' or HTTP referer.
  *
  * If it's the same as the current request URL, will return false.
  *
@@ -1951,13 +1966,16 @@
  * @return string|false Referer URL on success, false on failure.
  */
 function wp_get_referer() {
+	// Return early if called before wp_validate_redirect() is defined.
 	if ( ! function_exists( 'wp_validate_redirect' ) ) {
 		return false;
 	}
 
 	$ref = wp_get_raw_referer();
 
-	if ( $ref && wp_unslash( $_SERVER['REQUEST_URI'] ) !== $ref && home_url() . wp_unslash( $_SERVER['REQUEST_URI'] ) !== $ref ) {
+	if ( $ref && wp_unslash( $_SERVER['REQUEST_URI'] ) !== $ref
+		&& home_url() . wp_unslash( $_SERVER['REQUEST_URI'] ) !== $ref
+	) {
 		return wp_validate_redirect( $ref, false );
 	}
 
@@ -1965,7 +1983,9 @@
 }
 
 /**
- * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer.
+ * Retrieves unvalidated referer from the '_wp_http_referer' URL query variable or the HTTP referer.
+ *
+ * If the value of the '_wp_http_referer' URL query variable is not a string then it will be ignored.
  *
  * Do not use for redirects, use wp_get_referer() instead.
  *
@@ -1974,7 +1994,7 @@
  * @return string|false Referer URL on success, false on failure.
  */
 function wp_get_raw_referer() {
-	if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) {
+	if ( ! empty( $_REQUEST['_wp_http_referer'] ) && is_string( $_REQUEST['_wp_http_referer'] ) ) {
 		return wp_unslash( $_REQUEST['_wp_http_referer'] );
 	} elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
 		return wp_unslash( $_SERVER['HTTP_REFERER'] );
@@ -1984,14 +2004,19 @@
 }
 
 /**
- * Retrieve original referer that was posted, if it exists.
+ * Retrieves original referer that was posted, if it exists.
  *
  * @since 2.0.4
  *
  * @return string|false Original referer URL on success, false on failure.
  */
 function wp_get_original_referer() {
-	if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) && function_exists( 'wp_validate_redirect' ) ) {
+	// Return early if called before wp_validate_redirect() is defined.
+	if ( ! function_exists( 'wp_validate_redirect' ) ) {
+		return false;
+	}
+
+	if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) ) {
 		return wp_validate_redirect( wp_unslash( $_REQUEST['_wp_original_http_referer'] ), false );
 	}
 
@@ -2038,7 +2063,7 @@
 	}
 
 	// Do not allow path traversals.
-	if ( false !== strpos( $target, '../' ) || false !== strpos( $target, '..' . DIRECTORY_SEPARATOR ) ) {
+	if ( str_contains( $target, '../' ) || str_contains( $target, '..' . DIRECTORY_SEPARATOR ) ) {
 		return false;
 	}
 
@@ -2062,7 +2087,7 @@
 		 * If a umask is set that modifies $dir_perms, we'll have to re-set
 		 * the $dir_perms correctly with chmod()
 		 */
-		if ( ( $dir_perms & ~umask() ) != $dir_perms ) {
+		if ( ( $dir_perms & ~umask() ) !== $dir_perms ) {
 			$folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
 			for ( $i = 1, $c = count( $folder_parts ); $i <= $c; $i++ ) {
 				chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
@@ -2076,7 +2101,7 @@
 }
 
 /**
- * Test if a given filesystem path is absolute.
+ * Tests if a given filesystem path is absolute.
  *
  * For example, '/foo/bar', or 'c:\windows'.
  *
@@ -2098,11 +2123,11 @@
 	 * This is definitive if true but fails if $path does not exist or contains
 	 * a symbolic link.
 	 */
-	if ( realpath( $path ) == $path ) {
+	if ( realpath( $path ) === $path ) {
 		return true;
 	}
 
-	if ( strlen( $path ) == 0 || '.' === $path[0] ) {
+	if ( strlen( $path ) === 0 || '.' === $path[0] ) {
 		return false;
 	}
 
@@ -2116,7 +2141,7 @@
 }
 
 /**
- * Join two filesystem paths together.
+ * Joins two filesystem paths together.
  *
  * For example, 'give me $path relative to $base'. If the $path is absolute,
  * then it the full path is returned.
@@ -2132,11 +2157,11 @@
 		return $path;
 	}
 
-	return rtrim( $base, '/' ) . '/' . ltrim( $path, '/' );
-}
-
-/**
- * Normalize a filesystem path.
+	return rtrim( $base, '/' ) . '/' . $path;
+}
+
+/**
+ * Normalizes a filesystem path.
  *
  * On windows systems, replaces backslashes with forward slashes
  * and forces upper-case drive letters.
@@ -2175,7 +2200,7 @@
 }
 
 /**
- * Determine a writable directory for temporary files.
+ * Determines a writable directory for temporary files.
  *
  * Function's preference is the return value of sys_get_temp_dir(),
  * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR,
@@ -2219,7 +2244,7 @@
 }
 
 /**
- * Determine if a directory is writable.
+ * Determines if a directory is writable.
  *
  * This function is used to work around certain ACL issues in PHP primarily
  * affecting Windows Servers.
@@ -2245,7 +2270,7 @@
  * PHP has issues with Windows ACL's for determine if a
  * directory is writable or not, this works around them by
  * checking the ability to open files rather than relying
- * upon PHP to interprate the OS ACL.
+ * upon PHP to interpret the OS ACL.
  *
  * @since 2.8.0
  *
@@ -2319,10 +2344,10 @@
  * @since 2.0.0
  * @uses _wp_upload_dir()
  *
- * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
- * @param bool   $create_dir Optional. Whether to check and create the uploads directory.
- *                           Default true for backward compatibility.
- * @param bool   $refresh_cache Optional. Whether to refresh the cache. Default false.
+ * @param string|null $time          Optional. Time formatted in 'yyyy/mm'. Default null.
+ * @param bool        $create_dir    Optional. Whether to check and create the uploads directory.
+ *                                   Default true for backward compatibility.
+ * @param bool        $refresh_cache Optional. Whether to refresh the cache. Default false.
  * @return array {
  *     Array of information about the upload directory.
  *
@@ -2368,7 +2393,7 @@
 			$uploads['error'] = $tested_paths[ $path ];
 		} else {
 			if ( ! wp_mkdir_p( $path ) ) {
-				if ( 0 === strpos( $uploads['basedir'], ABSPATH ) ) {
+				if ( str_starts_with( $uploads['basedir'], ABSPATH ) ) {
 					$error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
 				} else {
 					$error_path = wp_basename( $uploads['basedir'] ) . $uploads['subdir'];
@@ -2394,7 +2419,7 @@
  * @since 4.5.0
  * @access private
  *
- * @param string $time Optional. Time formatted in 'yyyy/mm'. Default null.
+ * @param string|null $time Optional. Time formatted in 'yyyy/mm'. Default null.
  * @return array See wp_upload_dir()
  */
 function _wp_upload_dir( $time = null ) {
@@ -2403,7 +2428,7 @@
 
 	if ( empty( $upload_path ) || 'wp-content/uploads' === $upload_path ) {
 		$dir = WP_CONTENT_DIR . '/uploads';
-	} elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
+	} elseif ( ! str_starts_with( $upload_path, ABSPATH ) ) {
 		// $dir is absolute, $upload_path is (maybe) relative to ABSPATH.
 		$dir = path_join( ABSPATH, $upload_path );
 	} else {
@@ -2412,7 +2437,7 @@
 
 	$url = get_option( 'upload_url_path' );
 	if ( ! $url ) {
-		if ( empty( $upload_path ) || ( 'wp-content/uploads' === $upload_path ) || ( $upload_path == $dir ) ) {
+		if ( empty( $upload_path ) || ( 'wp-content/uploads' === $upload_path ) || ( $upload_path === $dir ) ) {
 			$url = WP_CONTENT_URL . '/uploads';
 		} else {
 			$url = trailingslashit( $siteurl ) . $upload_path;
@@ -2502,7 +2527,7 @@
 }
 
 /**
- * Get a filename that is sanitized and unique for the given directory.
+ * Gets a filename that is sanitized and unique for the given directory.
  *
  * If the filename is not unique, then a number will be added to the filename
  * before the extension, and will continue adding numbers until the filename
@@ -2565,7 +2590,7 @@
 		$file_type = wp_check_filetype( $filename );
 		$mime_type = $file_type['type'];
 
-		$is_image    = ( ! empty( $mime_type ) && 0 === strpos( $mime_type, 'image/' ) );
+		$is_image    = ( ! empty( $mime_type ) && str_starts_with( $mime_type, 'image/' ) );
 		$upload_dir  = wp_get_upload_dir();
 		$lc_filename = null;
 
@@ -2625,7 +2650,7 @@
 		$count = 10000;
 
 		// The (resized) image files would have name and extension, and will be in the uploads dir.
-		if ( $name && $ext && @is_dir( $dir ) && false !== strpos( $dir, $upload_dir['basedir'] ) ) {
+		if ( $name && $ext && @is_dir( $dir ) && str_contains( $dir, $upload_dir['basedir'] ) ) {
 			/**
 			 * Filters the file list used for calculating a unique filename for a newly added file.
 			 *
@@ -2671,7 +2696,7 @@
 					);
 
 					$number = $new_number;
-					$i++;
+					++$i;
 				}
 			}
 		}
@@ -2744,7 +2769,7 @@
 					);
 
 					$number = $new_number;
-					$i++;
+					++$i;
 				}
 			}
 		}
@@ -2827,7 +2852,7 @@
 }
 
 /**
- * Create a file in the upload folder with given content.
+ * Creates a file in the upload folder with given content.
  *
  * If there is an error, then the key 'error' will exist with the error message.
  * If success, then the key 'file' will have the unique file path, the 'url' key
@@ -2846,7 +2871,7 @@
  * @param string      $name       Filename.
  * @param null|string $deprecated Never used. Set to null.
  * @param string      $bits       File content
- * @param string      $time       Optional. Time formatted in 'yyyy/mm'. Default null.
+ * @param string|null $time       Optional. Time formatted in 'yyyy/mm'. Default null.
  * @return array {
  *     Information about the newly-uploaded file.
  *
@@ -2903,7 +2928,7 @@
 
 	$new_file = $upload['path'] . "/$filename";
 	if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
-		if ( 0 === strpos( $upload['basedir'], ABSPATH ) ) {
+		if ( str_starts_with( $upload['basedir'], ABSPATH ) ) {
 			$error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
 		} else {
 			$error_path = wp_basename( $upload['basedir'] ) . $upload['subdir'];
@@ -2957,7 +2982,7 @@
 }
 
 /**
- * Retrieve the file type based on the extension name.
+ * Retrieves the file type based on the extension name.
  *
  * @since 2.5.0
  *
@@ -2996,14 +3021,15 @@
 }
 
 /**
- * Retrieve the file type from the file name.
+ * Retrieves the file type from the file name.
  *
  * You can optionally define the mime array, if needed.
  *
  * @since 2.0.4
  *
- * @param string   $filename File name or path.
- * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
+ * @param string        $filename File name or path.
+ * @param string[]|null $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
+ *                                Defaults to the result of get_allowed_mime_types().
  * @return array {
  *     Values for the extension and mime type.
  *
@@ -3031,7 +3057,7 @@
 }
 
 /**
- * Attempt to determine the real file type of a file.
+ * Attempts to determine the real file type of a file.
  *
  * If unable to, the file name extension will be used to determine type.
  *
@@ -3042,10 +3068,11 @@
  *
  * @since 3.0.0
  *
- * @param string   $file     Full path to the file.
- * @param string   $filename The name of the file (may differ from $file due to $file being
- *                           in a tmp directory).
- * @param string[] $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
+ * @param string        $file     Full path to the file.
+ * @param string        $filename The name of the file (may differ from $file due to $file being
+ *                                in a tmp directory).
+ * @param string[]|null $mimes    Optional. Array of allowed mime types keyed by their file extension regex.
+ *                                Defaults to the result of get_allowed_mime_types().
  * @return array {
  *     Values for the extension, mime type, and corrected filename.
  *
@@ -3070,12 +3097,12 @@
 	$real_mime = false;
 
 	// Validate image types.
-	if ( $type && 0 === strpos( $type, 'image/' ) ) {
+	if ( $type && str_starts_with( $type, 'image/' ) ) {
 
 		// Attempt to figure out what type of image it actually is.
 		$real_mime = wp_get_image_mime( $file );
 
-		if ( $real_mime && $real_mime != $type ) {
+		if ( $real_mime && $real_mime !== $type ) {
 			/**
 			 * Filters the list mapping image mime types to their respective extensions.
 			 *
@@ -3092,6 +3119,7 @@
 					'image/bmp'  => 'bmp',
 					'image/tiff' => 'tif',
 					'image/webp' => 'webp',
+					'image/avif' => 'avif',
 				)
 			);
 
@@ -3102,9 +3130,10 @@
 				$filename_parts[] = $mime_to_ext[ $real_mime ];
 				$new_filename     = implode( '.', $filename_parts );
 
-				if ( $new_filename != $filename ) {
+				if ( $new_filename !== $filename ) {
 					$proper_filename = $new_filename; // Mark that it changed.
 				}
+
 				// Redefine the extension / MIME.
 				$wp_filetype = wp_check_filetype( $new_filename, $mimes );
 				$ext         = $wp_filetype['ext'];
@@ -3122,6 +3151,24 @@
 		$real_mime = finfo_file( $finfo, $file );
 		finfo_close( $finfo );
 
+		$google_docs_types = array(
+			'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+			'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+		);
+
+		foreach ( $google_docs_types as $google_docs_type ) {
+			/*
+			 * finfo_file() can return duplicate mime type for Google docs,
+			 * this conditional reduces it to a single instance.
+			 *
+			 * @see https://bugs.php.net/bug.php?id=77784
+			 * @see https://core.trac.wordpress.org/ticket/57898
+			 */
+			if ( 2 === substr_count( $real_mime, $google_docs_type ) ) {
+				$real_mime = $google_docs_type;
+			}
+		}
+
 		// fileinfo often misidentifies obscure files as one of these types.
 		$nonspecific_types = array(
 			'application/octet-stream',
@@ -3141,7 +3188,7 @@
 				$type = false;
 				$ext  = false;
 			}
-		} elseif ( 0 === strpos( $real_mime, 'video/' ) || 0 === strpos( $real_mime, 'audio/' ) ) {
+		} elseif ( str_starts_with( $real_mime, 'video/' ) || str_starts_with( $real_mime, 'audio/' ) ) {
 			/*
 			 * For these types, only the major type must match the real value.
 			 * This means that common mismatches are forgiven: application/vnd.apple.numbers is often misidentified as application/zip,
@@ -3227,18 +3274,19 @@
 	 * @since 3.0.0
 	 * @since 5.1.0 The $real_mime parameter was added.
 	 *
-	 * @param array        $wp_check_filetype_and_ext {
+	 * @param array         $wp_check_filetype_and_ext {
 	 *     Values for the extension, mime type, and corrected filename.
 	 *
 	 *     @type string|false $ext             File extension, or false if the file doesn't match a mime type.
 	 *     @type string|false $type            File mime type, or false if the file doesn't match a mime type.
 	 *     @type string|false $proper_filename File name with its correct extension, or false if it cannot be determined.
 	 * }
-	 * @param string       $file                      Full path to the file.
-	 * @param string       $filename                  The name of the file (may differ from $file due to
-	 *                                                $file being in a tmp directory).
-	 * @param string[]     $mimes                     Array of mime types keyed by their file extension regex.
-	 * @param string|false $real_mime                 The actual mime type or false if the type cannot be determined.
+	 * @param string        $file                      Full path to the file.
+	 * @param string        $filename                  The name of the file (may differ from $file due to
+	 *                                                 $file being in a tmp directory).
+	 * @param string[]|null $mimes                     Array of mime types keyed by their file extension regex, or null if
+	 *                                                 none were provided.
+	 * @param string|false  $real_mime                 The actual mime type or false if the type cannot be determined.
 	 */
 	return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes, $real_mime );
 }
@@ -3250,6 +3298,7 @@
  *
  * @since 4.7.1
  * @since 5.8.0 Added support for WebP images.
+ * @since 6.5.0 Added support for AVIF images.
  *
  * @param string $file Full path to the file.
  * @return string|false The actual mime type or false if the type cannot be determined.
@@ -3272,7 +3321,6 @@
 				// Not using wp_getimagesize() here to avoid an infinite loop.
 				$imagesize = getimagesize( $file );
 			} else {
-				// phpcs:ignore WordPress.PHP.NoSilencedErrors
 				$imagesize = @getimagesize( $file );
 			}
 
@@ -3299,12 +3347,31 @@
 		$magic = bin2hex( $magic );
 		if (
 			// RIFF.
-			( 0 === strpos( $magic, '52494646' ) ) &&
+			( str_starts_with( $magic, '52494646' ) ) &&
 			// WEBP.
 			( 16 === strpos( $magic, '57454250' ) )
 		) {
 			$mime = 'image/webp';
 		}
+
+		/**
+		 * Add AVIF fallback detection when image library doesn't support AVIF.
+		 *
+		 * Detection based on section 4.3.1 File-type box definition of the ISO/IEC 14496-12
+		 * specification and the AV1-AVIF spec, see https://aomediacodec.github.io/av1-avif/v1.1.0.html#brands.
+		 */
+
+		// Divide the header string into 4 byte groups.
+		$magic = str_split( $magic, 8 );
+
+		if (
+			isset( $magic[1] ) &&
+			isset( $magic[2] ) &&
+			'ftyp' === hex2bin( $magic[1] ) &&
+			( 'avif' === hex2bin( $magic[2] ) || 'avis' === hex2bin( $magic[2] ) )
+		) {
+			$mime = 'image/avif';
+		}
 	} catch ( Exception $e ) {
 		$mime = false;
 	}
@@ -3313,7 +3380,7 @@
 }
 
 /**
- * Retrieve list of mime types and file extensions.
+ * Retrieves the list of mime types and file extensions.
  *
  * @since 3.5.0
  * @since 4.2.0 Support was added for GIMP (.xcf) files.
@@ -3332,7 +3399,7 @@
 	 * @since 3.5.0
 	 *
 	 * @param string[] $wp_get_mime_types Mime types keyed by the file extension regex
-	 *                                 corresponding to those types.
+	 *                                    corresponding to those types.
 	 */
 	return apply_filters(
 		'mime_types',
@@ -3344,6 +3411,7 @@
 			'bmp'                          => 'image/bmp',
 			'tiff|tif'                     => 'image/tiff',
 			'webp'                         => 'image/webp',
+			'avif'                         => 'image/avif',
 			'ico'                          => 'image/x-icon',
 			'heic'                         => 'image/heic',
 			// Video formats.
@@ -3465,7 +3533,7 @@
 	return apply_filters(
 		'ext2type',
 		array(
-			'image'       => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic', 'webp' ),
+			'image'       => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico', 'heic', 'webp', 'avif' ),
 			'audio'       => array( 'aac', 'ac3', 'aif', 'aiff', 'flac', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
 			'video'       => array( '3g2', '3gp', '3gpp', 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
 			'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'xps', 'oxps', 'rtf', 'wp', 'wpd', 'psd', 'xcf' ),
@@ -3517,7 +3585,7 @@
 }
 
 /**
- * Retrieve list of allowed mime types and file extensions.
+ * Retrieves the list of allowed mime types and file extensions.
  *
  * @since 2.8.6
  *
@@ -3538,7 +3606,7 @@
 	}
 
 	/**
-	 * Filters list of allowed mime types and file extensions.
+	 * Filters the list of allowed mime types and file extensions.
 	 *
 	 * @since 2.0.0
 	 *
@@ -3549,7 +3617,7 @@
 }
 
 /**
- * Display "Are You Sure" message to confirm the action being taken.
+ * Displays "Are You Sure" message to confirm the action being taken.
  *
  * If the action has the nonce explain message, then it will be displayed
  * along with the "Are you sure?" message.
@@ -3569,21 +3637,27 @@
 			__( 'You are attempting to log out of %s' ),
 			get_bloginfo( 'name' )
 		);
-		$html        = $title;
-		$html       .= '</p><p>';
+
 		$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
-		$html       .= sprintf(
+
+		$html  = $title;
+		$html .= '</p><p>';
+		$html .= sprintf(
 			/* translators: %s: Logout URL. */
 			__( 'Do you really want to <a href="%s">log out</a>?' ),
 			wp_logout_url( $redirect_to )
 		);
 	} else {
 		$html = __( 'The link you followed has expired.' );
+
 		if ( wp_get_referer() ) {
+			$wp_http_referer = remove_query_arg( 'updated', wp_get_referer() );
+			$wp_http_referer = wp_validate_redirect( sanitize_url( $wp_http_referer ) );
+
 			$html .= '</p><p>';
 			$html .= sprintf(
 				'<a href="%s">%s</a>',
-				esc_url( remove_query_arg( 'updated', wp_get_referer() ) ),
+				esc_url( $wp_http_referer ),
 				__( 'Please try again.' )
 			);
 		}
@@ -3616,11 +3690,11 @@
  *
  * @param string|WP_Error  $message Optional. Error message. If this is a WP_Error object,
  *                                  and not an Ajax or XML-RPC request, the error's messages are used.
- *                                  Default empty.
+ *                                  Default empty string.
  * @param string|int       $title   Optional. Error title. If `$message` is a `WP_Error` object,
  *                                  error data with the key 'title' may be used to specify the title.
- *                                  If `$title` is an integer, then it is treated as the response
- *                                  code. Default empty.
+ *                                  If `$title` is an integer, then it is treated as the response code.
+ *                                  Default empty string.
  * @param string|array|int $args {
  *     Optional. Arguments to control behavior. If `$args` is an integer, then it is treated
  *     as the response code. Default empty array.
@@ -3668,7 +3742,7 @@
 		 * @param callable $callback Callback function name.
 		 */
 		$callback = apply_filters( 'wp_die_json_handler', '_json_wp_die_handler' );
-	} elseif ( defined( 'REST_REQUEST' ) && REST_REQUEST && wp_is_jsonp_request() ) {
+	} elseif ( wp_is_serving_rest_request() && wp_is_jsonp_request() ) {
 		/**
 		 * Filters the callback for killing WordPress execution for JSONP REST requests.
 		 *
@@ -3723,7 +3797,7 @@
  * @access private
  *
  * @param string|WP_Error $message Error message or WP_Error object.
- * @param string          $title   Optional. Error title. Default empty.
+ * @param string          $title   Optional. Error title. Default empty string.
  * @param string|array    $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -3770,8 +3844,10 @@
 		$text_direction = $parsed_args['text_direction'];
 		$dir_attr       = "dir='$text_direction'";
 
-		// If `text_direction` was not explicitly passed,
-		// use get_language_attributes() if available.
+		/*
+		 * If `text_direction` was not explicitly passed,
+		 * use get_language_attributes() if available.
+		 */
 		if ( empty( $args['text_direction'] )
 			&& function_exists( 'language_attributes' ) && function_exists( 'is_rtl' )
 		) {
@@ -3786,6 +3862,9 @@
 		<?php
 		if ( function_exists( 'wp_robots' ) && function_exists( 'wp_robots_no_robots' ) && function_exists( 'add_filter' ) ) {
 			add_filter( 'wp_robots', 'wp_robots_no_robots' );
+			// Prevent warnings because of $wp_query not existing.
+			remove_filter( 'wp_robots', 'wp_robots_noindex_embeds' );
+			remove_filter( 'wp_robots', 'wp_robots_noindex_search' );
 			wp_robots();
 		}
 		?>
@@ -3831,21 +3910,16 @@
 			font-size: 14px ;
 		}
 		a {
-			color: #0073aa;
+			color: #2271b1;
 		}
 		a:hover,
 		a:active {
-			color: #006799;
+			color: #135e96;
 		}
 		a:focus {
-			color: #124964;
-			-webkit-box-shadow:
-				0 0 0 1px #5b9dd9,
-				0 0 2px 1px rgba(30, 140, 190, 0.8);
-			box-shadow:
-				0 0 0 1px #5b9dd9,
-				0 0 2px 1px rgba(30, 140, 190, 0.8);
-			outline: none;
+			color: #043959;
+			box-shadow: 0 0 0 2px #2271b1;
+			outline: 2px solid transparent;
 		}
 		.button {
 			background: #f3f5f6;
@@ -3925,7 +3999,7 @@
  * @access private
  *
  * @param string       $message Error message.
- * @param string       $title   Optional. Error title (unused). Default empty.
+ * @param string       $title   Optional. Error title (unused). Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _ajax_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -3967,7 +4041,7 @@
  * @access private
  *
  * @param string       $message Error message.
- * @param string       $title   Optional. Error title. Default empty.
+ * @param string       $title   Optional. Error title. Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _json_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -3982,6 +4056,10 @@
 		'additional_errors' => $parsed_args['additional_errors'],
 	);
 
+	if ( isset( $parsed_args['error_data'] ) ) {
+		$data['data']['error'] = $parsed_args['error_data'];
+	}
+
 	if ( ! headers_sent() ) {
 		header( "Content-Type: application/json; charset={$parsed_args['charset']}" );
 		if ( null !== $parsed_args['response'] ) {
@@ -4005,7 +4083,7 @@
  * @access private
  *
  * @param string       $message Error message.
- * @param string       $title   Optional. Error title. Default empty.
+ * @param string       $title   Optional. Error title. Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _jsonp_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -4020,6 +4098,10 @@
 		'additional_errors' => $parsed_args['additional_errors'],
 	);
 
+	if ( isset( $parsed_args['error_data'] ) ) {
+		$data['data']['error'] = $parsed_args['error_data'];
+	}
+
 	if ( ! headers_sent() ) {
 		header( "Content-Type: application/javascript; charset={$parsed_args['charset']}" );
 		header( 'X-Content-Type-Options: nosniff' );
@@ -4049,7 +4131,7 @@
  * @global wp_xmlrpc_server $wp_xmlrpc_server
  *
  * @param string       $message Error message.
- * @param string       $title   Optional. Error title. Default empty.
+ * @param string       $title   Optional. Error title. Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -4079,7 +4161,7 @@
  * @access private
  *
  * @param string       $message Error message.
- * @param string       $title   Optional. Error title. Default empty.
+ * @param string       $title   Optional. Error title. Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _xml_wp_die_handler( $message, $title = '', $args = array() ) {
@@ -4123,8 +4205,8 @@
  * @since 5.1.0 Added the $title and $args parameters.
  * @access private
  *
- * @param string       $message Optional. Response to print. Default empty.
- * @param string       $title   Optional. Error title (unused). Default empty.
+ * @param string       $message Optional. Response to print. Default empty string.
+ * @param string       $title   Optional. Error title (unused). Default empty string.
  * @param string|array $args    Optional. Arguments to control behavior. Default empty array.
  */
 function _scalar_wp_die_handler( $message = '', $title = '', $args = array() ) {
@@ -4149,7 +4231,7 @@
  * @access private
  *
  * @param string|WP_Error $message Error message or WP_Error object.
- * @param string          $title   Optional. Error title. Default empty.
+ * @param string          $title   Optional. Error title. Default empty string.
  * @param string|array    $args    Optional. Arguments to control behavior. Default empty array.
  * @return array {
  *     Processed arguments.
@@ -4197,6 +4279,9 @@
 			if ( empty( $title ) && is_array( $errors[0]['data'] ) && ! empty( $errors[0]['data']['title'] ) ) {
 				$title = $errors[0]['data']['title'];
 			}
+			if ( WP_DEBUG_DISPLAY && is_array( $errors[0]['data'] ) && ! empty( $errors[0]['data']['error'] ) ) {
+				$args['error_data'] = $errors[0]['data']['error'];
+			}
 
 			unset( $errors[0] );
 			$args['additional_errors'] = array_values( $errors );
@@ -4232,36 +4317,38 @@
 }
 
 /**
- * Encode a variable into JSON, with some sanity checks.
+ * Encodes a variable into JSON, with some confidence checks.
  *
  * @since 4.1.0
  * @since 5.3.0 No longer handles support for PHP < 5.6.
- *
- * @param mixed $data    Variable (usually an array or object) to encode as JSON.
- * @param int   $options Optional. Options to be passed to json_encode(). Default 0.
- * @param int   $depth   Optional. Maximum depth to walk through $data. Must be
- *                       greater than 0. Default 512.
+ * @since 6.5.0 The `$data` parameter has been renamed to `$value` and
+ *              the `$options` parameter to `$flags` for parity with PHP.
+ *
+ * @param mixed $value Variable (usually an array or object) to encode as JSON.
+ * @param int   $flags Optional. Options to be passed to json_encode(). Default 0.
+ * @param int   $depth Optional. Maximum depth to walk through $value. Must be
+ *                     greater than 0. Default 512.
  * @return string|false The JSON encoded string, or false if it cannot be encoded.
  */
-function wp_json_encode( $data, $options = 0, $depth = 512 ) {
-	$json = json_encode( $data, $options, $depth );
-
-	// If json_encode() was successful, no need to do more sanity checking.
+function wp_json_encode( $value, $flags = 0, $depth = 512 ) {
+	$json = json_encode( $value, $flags, $depth );
+
+	// If json_encode() was successful, no need to do more confidence checking.
 	if ( false !== $json ) {
 		return $json;
 	}
 
 	try {
-		$data = _wp_json_sanity_check( $data, $depth );
+		$value = _wp_json_sanity_check( $value, $depth );
 	} catch ( Exception $e ) {
 		return false;
 	}
 
-	return json_encode( $data, $options, $depth );
-}
-
-/**
- * Perform sanity checks on data that shall be encoded to JSON.
+	return json_encode( $value, $flags, $depth );
+}
+
+/**
+ * Performs confidence checks on data that shall be encoded to JSON.
  *
  * @ignore
  * @since 4.1.0
@@ -4271,18 +4358,18 @@
  *
  * @throws Exception If depth limit is reached.
  *
- * @param mixed $data  Variable (usually an array or object) to encode as JSON.
- * @param int   $depth Maximum depth to walk through $data. Must be greater than 0.
+ * @param mixed $value Variable (usually an array or object) to encode as JSON.
+ * @param int   $depth Maximum depth to walk through $value. Must be greater than 0.
  * @return mixed The sanitized data that shall be encoded to JSON.
  */
-function _wp_json_sanity_check( $data, $depth ) {
+function _wp_json_sanity_check( $value, $depth ) {
 	if ( $depth < 0 ) {
 		throw new Exception( 'Reached depth limit' );
 	}
 
-	if ( is_array( $data ) ) {
+	if ( is_array( $value ) ) {
 		$output = array();
-		foreach ( $data as $id => $el ) {
+		foreach ( $value as $id => $el ) {
 			// Don't forget to sanitize the ID!
 			if ( is_string( $id ) ) {
 				$clean_id = _wp_json_convert_string( $id );
@@ -4299,9 +4386,9 @@
 				$output[ $clean_id ] = $el;
 			}
 		}
-	} elseif ( is_object( $data ) ) {
-		$output = new stdClass;
-		foreach ( $data as $id => $el ) {
+	} elseif ( is_object( $value ) ) {
+		$output = new stdClass();
+		foreach ( $value as $id => $el ) {
 			if ( is_string( $id ) ) {
 				$clean_id = _wp_json_convert_string( $id );
 			} else {
@@ -4316,17 +4403,17 @@
 				$output->$clean_id = $el;
 			}
 		}
-	} elseif ( is_string( $data ) ) {
-		return _wp_json_convert_string( $data );
+	} elseif ( is_string( $value ) ) {
+		return _wp_json_convert_string( $value );
 	} else {
-		return $data;
+		return $value;
 	}
 
 	return $output;
 }
 
 /**
- * Convert a string to UTF-8, so that it can be safely encoded to JSON.
+ * Converts a string to UTF-8, so that it can be safely encoded to JSON.
  *
  * @ignore
  * @since 4.1.0
@@ -4334,24 +4421,24 @@
  *
  * @see _wp_json_sanity_check()
  *
- * @param string $string The string which is to be converted.
+ * @param string $input_string The string which is to be converted.
  * @return string The checked string.
  */
-function _wp_json_convert_string( $string ) {
+function _wp_json_convert_string( $input_string ) {
 	static $use_mb = null;
 	if ( is_null( $use_mb ) ) {
 		$use_mb = function_exists( 'mb_convert_encoding' );
 	}
 
 	if ( $use_mb ) {
-		$encoding = mb_detect_encoding( $string, mb_detect_order(), true );
+		$encoding = mb_detect_encoding( $input_string, mb_detect_order(), true );
 		if ( $encoding ) {
-			return mb_convert_encoding( $string, 'UTF-8', $encoding );
+			return mb_convert_encoding( $input_string, 'UTF-8', $encoding );
 		} else {
-			return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
+			return mb_convert_encoding( $input_string, 'UTF-8', 'UTF-8' );
 		}
 	} else {
-		return wp_check_invalid_utf8( $string, true );
+		return wp_check_invalid_utf8( $input_string, true );
 	}
 }
 
@@ -4366,28 +4453,28 @@
  *                   has been dropped.
  * @access private
  *
- * @param mixed $data Native representation.
+ * @param mixed $value Native representation.
  * @return bool|int|float|null|string|array Data ready for `json_encode()`.
  */
-function _wp_json_prepare_data( $data ) {
+function _wp_json_prepare_data( $value ) {
 	_deprecated_function( __FUNCTION__, '5.3.0' );
-	return $data;
-}
-
-/**
- * Send a JSON response back to an Ajax request.
+	return $value;
+}
+
+/**
+ * Sends a JSON response back to an Ajax request.
  *
  * @since 3.5.0
  * @since 4.7.0 The `$status_code` parameter was added.
- * @since 5.6.0 The `$options` parameter was added.
+ * @since 5.6.0 The `$flags` parameter was added.
  *
  * @param mixed $response    Variable (usually an array or object) to encode as JSON,
  *                           then print and die.
  * @param int   $status_code Optional. The HTTP status code to output. Default null.
- * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
- */
-function wp_send_json( $response, $status_code = null, $options = 0 ) {
-	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
+ * @param int   $flags       Optional. Options to be passed to json_encode(). Default 0.
+ */
+function wp_send_json( $response, $status_code = null, $flags = 0 ) {
+	if ( wp_is_serving_rest_request() ) {
 		_doing_it_wrong(
 			__FUNCTION__,
 			sprintf(
@@ -4407,7 +4494,7 @@
 		}
 	}
 
-	echo wp_json_encode( $response, $options );
+	echo wp_json_encode( $response, $flags );
 
 	if ( wp_doing_ajax() ) {
 		wp_die(
@@ -4423,50 +4510,50 @@
 }
 
 /**
- * Send a JSON response back to an Ajax request, indicating success.
+ * Sends a JSON response back to an Ajax request, indicating success.
  *
  * @since 3.5.0
  * @since 4.7.0 The `$status_code` parameter was added.
- * @since 5.6.0 The `$options` parameter was added.
- *
- * @param mixed $data        Optional. Data to encode as JSON, then print and die. Default null.
+ * @since 5.6.0 The `$flags` parameter was added.
+ *
+ * @param mixed $value       Optional. Data to encode as JSON, then print and die. Default null.
  * @param int   $status_code Optional. The HTTP status code to output. Default null.
- * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
- */
-function wp_send_json_success( $data = null, $status_code = null, $options = 0 ) {
+ * @param int   $flags       Optional. Options to be passed to json_encode(). Default 0.
+ */
+function wp_send_json_success( $value = null, $status_code = null, $flags = 0 ) {
 	$response = array( 'success' => true );
 
-	if ( isset( $data ) ) {
-		$response['data'] = $data;
-	}
-
-	wp_send_json( $response, $status_code, $options );
-}
-
-/**
- * Send a JSON response back to an Ajax request, indicating failure.
- *
- * If the `$data` parameter is a WP_Error object, the errors
+	if ( isset( $value ) ) {
+		$response['data'] = $value;
+	}
+
+	wp_send_json( $response, $status_code, $flags );
+}
+
+/**
+ * Sends a JSON response back to an Ajax request, indicating failure.
+ *
+ * If the `$value` parameter is a WP_Error object, the errors
  * within the object are processed and output as an array of error
  * codes and corresponding messages. All other types are output
  * without further processing.
  *
  * @since 3.5.0
- * @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in.
+ * @since 4.1.0 The `$value` parameter is now processed if a WP_Error object is passed in.
  * @since 4.7.0 The `$status_code` parameter was added.
- * @since 5.6.0 The `$options` parameter was added.
- *
- * @param mixed $data        Optional. Data to encode as JSON, then print and die. Default null.
+ * @since 5.6.0 The `$flags` parameter was added.
+ *
+ * @param mixed $value       Optional. Data to encode as JSON, then print and die. Default null.
  * @param int   $status_code Optional. The HTTP status code to output. Default null.
- * @param int   $options     Optional. Options to be passed to json_encode(). Default 0.
- */
-function wp_send_json_error( $data = null, $status_code = null, $options = 0 ) {
+ * @param int   $flags       Optional. Options to be passed to json_encode(). Default 0.
+ */
+function wp_send_json_error( $value = null, $status_code = null, $flags = 0 ) {
 	$response = array( 'success' => false );
 
-	if ( isset( $data ) ) {
-		if ( is_wp_error( $data ) ) {
+	if ( isset( $value ) ) {
+		if ( is_wp_error( $value ) ) {
 			$result = array();
-			foreach ( $data->errors as $code => $messages ) {
+			foreach ( $value->errors as $code => $messages ) {
 				foreach ( $messages as $message ) {
 					$result[] = array(
 						'code'    => $code,
@@ -4477,11 +4564,11 @@
 
 			$response['data'] = $result;
 		} else {
-			$response['data'] = $data;
-		}
-	}
-
-	wp_send_json( $response, $status_code, $options );
+			$response['data'] = $value;
+		}
+	}
+
+	wp_send_json( $response, $status_code, $flags );
 }
 
 /**
@@ -4516,7 +4603,7 @@
  *     Optional. Options to be used with `json_decode()`.
  *
  *     @type bool $associative Optional. When `true`, JSON objects will be returned as associative arrays.
- *                             When `false`, JSON objects will be returned as objects.
+ *                             When `false`, JSON objects will be returned as objects. Default false.
  * }
  *
  * @return mixed Returns the value encoded in JSON in appropriate PHP type.
@@ -4525,8 +4612,10 @@
 function wp_json_file_decode( $filename, $options = array() ) {
 	$result   = null;
 	$filename = wp_normalize_path( realpath( $filename ) );
-	if ( ! file_exists( $filename ) ) {
-		trigger_error(
+
+	if ( ! $filename ) {
+		wp_trigger_error(
+			__FUNCTION__,
 			sprintf(
 				/* translators: %s: Path to the JSON file. */
 				__( "File %s doesn't exist!" ),
@@ -4540,7 +4629,8 @@
 	$decoded_file = json_decode( file_get_contents( $filename ), $options['associative'] );
 
 	if ( JSON_ERROR_NONE !== json_last_error() ) {
-		trigger_error(
+		wp_trigger_error(
+			__FUNCTION__,
 			sprintf(
 				/* translators: 1: Path to the JSON file, 2: Error message. */
 				__( 'Error when decoding a JSON file at path %1$s: %2$s' ),
@@ -4555,7 +4645,7 @@
 }
 
 /**
- * Retrieve the WordPress home page URL.
+ * Retrieves the WordPress home page URL.
  *
  * If the constant named 'WP_HOME' exists, then it will be used and returned
  * by the function. This can be used to counter the redirection on your local
@@ -4577,7 +4667,7 @@
 }
 
 /**
- * Retrieve the WordPress site URL.
+ * Retrieves the WordPress site URL.
  *
  * If the constant named 'WP_SITEURL' is defined, then the value in that
  * constant will always be returned. This can be used for debugging a site
@@ -4599,7 +4689,7 @@
 }
 
 /**
- * Delete the fresh site option.
+ * Deletes the fresh site option.
  *
  * @since 4.7.0
  * @access private
@@ -4609,7 +4699,7 @@
 }
 
 /**
- * Set the localized direction for MCE plugin.
+ * Sets the localized direction for MCE plugin.
  *
  * Will only set the direction to 'rtl', if the WordPress locale has
  * the text direction set to 'rtl'.
@@ -4630,7 +4720,7 @@
 		$mce_init['directionality'] = 'rtl';
 		$mce_init['rtl_ui']         = true;
 
-		if ( ! empty( $mce_init['plugins'] ) && strpos( $mce_init['plugins'], 'directionality' ) === false ) {
+		if ( ! empty( $mce_init['plugins'] ) && ! str_contains( $mce_init['plugins'], 'directionality' ) ) {
 			$mce_init['plugins'] .= ',directionality';
 		}
 
@@ -4642,9 +4732,26 @@
 	return $mce_init;
 }
 
-
-/**
- * Convert smiley code to the icon graphic file equivalent.
+/**
+ * Determines whether WordPress is currently serving a REST API request.
+ *
+ * The function relies on the 'REST_REQUEST' global. As such, it only returns true when an actual REST _request_ is
+ * being made. It does not return true when a REST endpoint is hit as part of another request, e.g. for preloading a
+ * REST response. See {@see wp_is_rest_endpoint()} for that purpose.
+ *
+ * This function should not be called until the {@see 'parse_request'} action, as the constant is only defined then,
+ * even for an actual REST request.
+ *
+ * @since 6.5.0
+ *
+ * @return bool True if it's a WordPress REST API request, false otherwise.
+ */
+function wp_is_serving_rest_request() {
+	return defined( 'REST_REQUEST' ) && REST_REQUEST;
+}
+
+/**
+ * Converts smiley code to the icon graphic file equivalent.
  *
  * You can turn off smilies, by going to the write setting screen and unchecking
  * the box, or by setting 'use_smilies' option to false or removing the option.
@@ -4660,10 +4767,10 @@
  * the description. Probably should create a Codex page for it, so that it is
  * available.
  *
+ * @since 2.2.0
+ *
  * @global array $wpsmiliestrans
  * @global array $wp_smiliessearch
- *
- * @since 2.2.0
  */
 function smilies_init() {
 	global $wpsmiliestrans, $wp_smiliessearch;
@@ -4735,7 +4842,7 @@
 	 */
 	$wpsmiliestrans = apply_filters( 'smilies', $wpsmiliestrans );
 
-	if ( count( $wpsmiliestrans ) == 0 ) {
+	if ( count( $wpsmiliestrans ) === 0 ) {
 		return;
 	}
 
@@ -4757,21 +4864,22 @@
 		$rest      = substr( $smiley, 1 );
 
 		// New subpattern?
-		if ( $firstchar != $subchar ) {
+		if ( $firstchar !== $subchar ) {
 			if ( '' !== $subchar ) {
 				$wp_smiliessearch .= ')(?=' . $spaces . '|$)';  // End previous "subpattern".
 				$wp_smiliessearch .= '|(?<=' . $spaces . '|^)'; // Begin another "subpattern".
 			}
+
 			$subchar           = $firstchar;
 			$wp_smiliessearch .= preg_quote( $firstchar, '/' ) . '(?:';
 		} else {
 			$wp_smiliessearch .= '|';
 		}
+
 		$wp_smiliessearch .= preg_quote( $rest, '/' );
 	}
 
 	$wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
-
 }
 
 /**
@@ -4808,15 +4916,18 @@
  *
  * @since 5.1.0
  *
- * @param array|string $list List of values.
+ * @param array|string $input_list List of values.
  * @return array Array of values.
  */
-function wp_parse_list( $list ) {
-	if ( ! is_array( $list ) ) {
-		return preg_split( '/[\s,]+/', $list, -1, PREG_SPLIT_NO_EMPTY );
-	}
-
-	return $list;
+function wp_parse_list( $input_list ) {
+	if ( ! is_array( $input_list ) ) {
+		return preg_split( '/[\s,]+/', $input_list, -1, PREG_SPLIT_NO_EMPTY );
+	}
+
+	// Validate all entries of the list are scalar.
+	$input_list = array_filter( $input_list, 'is_scalar' );
+
+	return $input_list;
 }
 
 /**
@@ -4825,13 +4936,13 @@
  * @since 3.0.0
  * @since 5.1.0 Refactored to use wp_parse_list().
  *
- * @param array|string $list List of IDs.
+ * @param array|string $input_list List of IDs.
  * @return int[] Sanitized array of IDs.
  */
-function wp_parse_id_list( $list ) {
-	$list = wp_parse_list( $list );
-
-	return array_unique( array_map( 'absint', $list ) );
+function wp_parse_id_list( $input_list ) {
+	$input_list = wp_parse_list( $input_list );
+
+	return array_unique( array_map( 'absint', $input_list ) );
 }
 
 /**
@@ -4840,30 +4951,30 @@
  * @since 4.7.0
  * @since 5.1.0 Refactored to use wp_parse_list().
  *
- * @param array|string $list List of slugs.
+ * @param array|string $input_list List of slugs.
  * @return string[] Sanitized array of slugs.
  */
-function wp_parse_slug_list( $list ) {
-	$list = wp_parse_list( $list );
-
-	return array_unique( array_map( 'sanitize_title', $list ) );
-}
-
-/**
- * Extract a slice of an array, given a list of keys.
+function wp_parse_slug_list( $input_list ) {
+	$input_list = wp_parse_list( $input_list );
+
+	return array_unique( array_map( 'sanitize_title', $input_list ) );
+}
+
+/**
+ * Extracts a slice of an array, given a list of keys.
  *
  * @since 3.1.0
  *
- * @param array $array The original array.
- * @param array $keys  The list of keys.
+ * @param array $input_array The original array.
+ * @param array $keys        The list of keys.
  * @return array The array slice.
  */
-function wp_array_slice_assoc( $array, $keys ) {
+function wp_array_slice_assoc( $input_array, $keys ) {
 	$slice = array();
 
 	foreach ( $keys as $key ) {
-		if ( isset( $array[ $key ] ) ) {
-			$slice[ $key ] = $array[ $key ];
+		if ( isset( $input_array[ $key ] ) ) {
+			$slice[ $key ] = $input_array[ $key ];
 		}
 	}
 
@@ -4871,6 +4982,26 @@
 }
 
 /**
+ * Sorts the keys of an array alphabetically.
+ *
+ * The array is passed by reference so it doesn't get returned
+ * which mimics the behavior of `ksort()`.
+ *
+ * @since 6.0.0
+ *
+ * @param array $input_array The array to sort, passed by reference.
+ */
+function wp_recursive_ksort( &$input_array ) {
+	foreach ( $input_array as &$value ) {
+		if ( is_array( $value ) ) {
+			wp_recursive_ksort( $value );
+		}
+	}
+
+	ksort( $input_array );
+}
+
+/**
  * Accesses an array in depth based on a path of keys.
  *
  * It is the PHP equivalent of JavaScript's `lodash.get()` and mirroring it may help other components
@@ -4878,44 +5009,65 @@
  *
  * Example usage:
  *
- *     $array = array(
+ *     $input_array = array(
  *         'a' => array(
  *             'b' => array(
  *                 'c' => 1,
  *             ),
  *         ),
  *     );
- *     _wp_array_get( $array, array( 'a', 'b', 'c' ) );
+ *     _wp_array_get( $input_array, array( 'a', 'b', 'c' ) );
  *
  * @internal
  *
  * @since 5.6.0
  * @access private
  *
- * @param array $array   An array from which we want to retrieve some information.
- * @param array $path    An array of keys describing the path with which to retrieve information.
- * @param mixed $default The return value if the path does not exist within the array,
- *                       or if `$array` or `$path` are not arrays.
+ * @param array $input_array   An array from which we want to retrieve some information.
+ * @param array $path          An array of keys describing the path with which to retrieve information.
+ * @param mixed $default_value Optional. The return value if the path does not exist within the array,
+ *                             or if `$input_array` or `$path` are not arrays. Default null.
  * @return mixed The value from the path specified.
  */
-function _wp_array_get( $array, $path, $default = null ) {
+function _wp_array_get( $input_array, $path, $default_value = null ) {
 	// Confirm $path is valid.
 	if ( ! is_array( $path ) || 0 === count( $path ) ) {
-		return $default;
+		return $default_value;
 	}
 
 	foreach ( $path as $path_element ) {
-		if (
-			! is_array( $array ) ||
-			( ! is_string( $path_element ) && ! is_integer( $path_element ) && ! is_null( $path_element ) ) ||
-			! array_key_exists( $path_element, $array )
+		if ( ! is_array( $input_array ) ) {
+			return $default_value;
+		}
+
+		if ( is_string( $path_element )
+			|| is_integer( $path_element )
+			|| null === $path_element
 		) {
-			return $default;
-		}
-		$array = $array[ $path_element ];
-	}
-
-	return $array;
+			/*
+			 * Check if the path element exists in the input array.
+			 * We check with `isset()` first, as it is a lot faster
+			 * than `array_key_exists()`.
+			 */
+			if ( isset( $input_array[ $path_element ] ) ) {
+				$input_array = $input_array[ $path_element ];
+				continue;
+			}
+
+			/*
+			 * If `isset()` returns false, we check with `array_key_exists()`,
+			 * which also checks for `null` values.
+			 */
+			if ( array_key_exists( $path_element, $input_array ) ) {
+				$input_array = $input_array[ $path_element ];
+				continue;
+			}
+		}
+
+		return $default_value;
+	}
+
+	return $input_array;
 }
 
 /**
@@ -4926,10 +5078,10 @@
  *
  * Example usage:
  *
- *     $array = array();
- *     _wp_array_set( $array, array( 'a', 'b', 'c', 1 ) );
- *
- *     $array becomes:
+ *     $input_array = array();
+ *     _wp_array_set( $input_array, array( 'a', 'b', 'c', 1 ) );
+ *
+ *     $input_array becomes:
  *     array(
  *         'a' => array(
  *             'b' => array(
@@ -4943,13 +5095,13 @@
  * @since 5.8.0
  * @access private
  *
- * @param array $array An array that we want to mutate to include a specific value in a path.
- * @param array $path  An array of keys describing the path that we want to mutate.
- * @param mixed $value The value that will be set.
- */
-function _wp_array_set( &$array, $path, $value = null ) {
-	// Confirm $array is valid.
-	if ( ! is_array( $array ) ) {
+ * @param array $input_array An array that we want to mutate to include a specific value in a path.
+ * @param array $path        An array of keys describing the path that we want to mutate.
+ * @param mixed $value       The value that will be set.
+ */
+function _wp_array_set( &$input_array, $path, $value = null ) {
+	// Confirm $input_array is valid.
+	if ( ! is_array( $input_array ) ) {
 		return;
 	}
 
@@ -4976,15 +5128,15 @@
 	for ( $i = 0; $i < $path_length - 1; ++$i ) {
 		$path_element = $path[ $i ];
 		if (
-			! array_key_exists( $path_element, $array ) ||
-			! is_array( $array[ $path_element ] )
+			! array_key_exists( $path_element, $input_array ) ||
+			! is_array( $input_array[ $path_element ] )
 		) {
-			$array[ $path_element ] = array();
-		}
-		$array = &$array[ $path_element ]; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.VariableRedeclaration
-	}
-
-	$array[ $path[ $i ] ] = $value;
+			$input_array[ $path_element ] = array();
+		}
+		$input_array = &$input_array[ $path_element ];
+	}
+
+	$input_array[ $path[ $i ] ] = $value;
 }
 
 /**
@@ -5008,14 +5160,13 @@
  * @link https://github.com/lodash-php/lodash-php/blob/master/src/String/kebabCase.php
  * @link https://github.com/lodash-php/lodash-php/blob/master/src/internal/unicodeWords.php
  *
- * @param string $string The string to kebab-case.
+ * @param string $input_string The string to kebab-case.
  *
  * @return string kebab-cased-string.
  */
-function _wp_to_kebab_case( $string ) {
-	//phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
-	// ignore the camelCase names for variables so the names are the same as lodash
-	// so comparing and porting new changes is easier.
+function _wp_to_kebab_case( $input_string ) {
+	// Ignore the camelCase names for variables so the names are the same as lodash so comparing and porting new changes is easier.
+	// phpcs:disable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
 
 	/*
 	 * Some notable things we've removed compared to the lodash version are:
@@ -5059,9 +5210,9 @@
 		)
 	) . '/u';
 
-	preg_match_all( $regexp, str_replace( "'", '', $string ), $matches );
+	preg_match_all( $regexp, str_replace( "'", '', $input_string ), $matches );
 	return strtolower( implode( '-', $matches[0] ) );
-	//phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
+	// phpcs:enable WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
 }
 
 /**
@@ -5100,23 +5251,23 @@
  * @since 3.0.0
  * @since 4.7.0 Uses `WP_List_Util` class.
  *
- * @param array       $list     An array of objects to filter.
- * @param array       $args     Optional. An array of key => value arguments to match
- *                              against each object. Default empty array.
- * @param string      $operator Optional. The logical operation to perform. 'AND' means
- *                              all elements from the array must match. 'OR' means only
- *                              one element needs to match. 'NOT' means no elements may
- *                              match. Default 'AND'.
- * @param bool|string $field    Optional. A field from the object to place instead
- *                              of the entire object. Default false.
+ * @param array       $input_list An array of objects to filter.
+ * @param array       $args       Optional. An array of key => value arguments to match
+ *                                against each object. Default empty array.
+ * @param string      $operator   Optional. The logical operation to perform. 'AND' means
+ *                                all elements from the array must match. 'OR' means only
+ *                                one element needs to match. 'NOT' means no elements may
+ *                                match. Default 'AND'.
+ * @param bool|string $field      Optional. A field from the object to place instead
+ *                                of the entire object. Default false.
  * @return array A list of objects or object fields.
  */
-function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
-	if ( ! is_array( $list ) ) {
+function wp_filter_object_list( $input_list, $args = array(), $operator = 'and', $field = false ) {
+	if ( ! is_array( $input_list ) ) {
 		return array();
 	}
 
-	$util = new WP_List_Util( $list );
+	$util = new WP_List_Util( $input_list );
 
 	$util->filter( $args, $operator );
 
@@ -5144,17 +5295,17 @@
  * @since 4.7.0 Uses `WP_List_Util` class.
  * @since 5.9.0 Converted into a wrapper for `wp_filter_object_list()`.
  *
- * @param array  $list     An array of objects to filter.
- * @param array  $args     Optional. An array of key => value arguments to match
- *                         against each object. Default empty array.
- * @param string $operator Optional. The logical operation to perform. 'AND' means
- *                         all elements from the array must match. 'OR' means only
- *                         one element needs to match. 'NOT' means no elements may
- *                         match. Default 'AND'.
+ * @param array  $input_list An array of objects to filter.
+ * @param array  $args       Optional. An array of key => value arguments to match
+ *                           against each object. Default empty array.
+ * @param string $operator   Optional. The logical operation to perform. 'AND' means
+ *                           all elements from the array must match. 'OR' means only
+ *                           one element needs to match. 'NOT' means no elements may
+ *                           match. Default 'AND'.
  * @return array Array of found values.
  */
-function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
-	return wp_filter_object_list( $list, $args, $operator );
+function wp_list_filter( $input_list, $args = array(), $operator = 'AND' ) {
+	return wp_filter_object_list( $input_list, $args, $operator );
 }
 
 /**
@@ -5167,20 +5318,20 @@
  * @since 4.0.0 $index_key parameter added.
  * @since 4.7.0 Uses `WP_List_Util` class.
  *
- * @param array      $list      List of objects or arrays.
- * @param int|string $field     Field from the object to place instead of the entire object.
- * @param int|string $index_key Optional. Field from the object to use as keys for the new array.
- *                              Default null.
+ * @param array      $input_list List of objects or arrays.
+ * @param int|string $field      Field from the object to place instead of the entire object.
+ * @param int|string $index_key  Optional. Field from the object to use as keys for the new array.
+ *                               Default null.
  * @return array Array of found values. If `$index_key` is set, an array of found values with keys
  *               corresponding to `$index_key`. If `$index_key` is null, array keys from the original
- *               `$list` will be preserved in the results.
- */
-function wp_list_pluck( $list, $field, $index_key = null ) {
-	if ( ! is_array( $list ) ) {
+ *               `$input_list` will be preserved in the results.
+ */
+function wp_list_pluck( $input_list, $field, $index_key = null ) {
+	if ( ! is_array( $input_list ) ) {
 		return array();
 	}
 
-	$util = new WP_List_Util( $list );
+	$util = new WP_List_Util( $input_list );
 
 	return $util->pluck( $field, $index_key );
 }
@@ -5190,20 +5341,21 @@
  *
  * @since 4.7.0
  *
- * @param array        $list          An array of objects to sort.
+ * @param array        $input_list    An array of objects or arrays to sort.
  * @param string|array $orderby       Optional. Either the field name to order by or an array
- *                                    of multiple orderby fields as $orderby => $order.
- * @param string       $order         Optional. Either 'ASC' or 'DESC'. Only used if $orderby
- *                                    is a string.
+ *                                    of multiple orderby fields as `$orderby => $order`.
+ *                                    Default empty array.
+ * @param string       $order         Optional. Either 'ASC' or 'DESC'. Only used if `$orderby`
+ *                                    is a string. Default 'ASC'.
  * @param bool         $preserve_keys Optional. Whether to preserve keys. Default false.
  * @return array The sorted array.
  */
-function wp_list_sort( $list, $orderby = array(), $order = 'ASC', $preserve_keys = false ) {
-	if ( ! is_array( $list ) ) {
+function wp_list_sort( $input_list, $orderby = array(), $order = 'ASC', $preserve_keys = false ) {
+	if ( ! is_array( $input_list ) ) {
 		return array();
 	}
 
-	$util = new WP_List_Util( $list );
+	$util = new WP_List_Util( $input_list );
 
 	return $util->sort( $orderby, $order, $preserve_keys );
 }
@@ -5238,7 +5390,7 @@
 }
 
 /**
- * Append the Widgets menu to the themes main menu.
+ * Appends the Widgets menu to the themes main menu.
  *
  * @since 2.2.0
  * @since 5.9.3 Don't specify menu order when the active theme is a block theme.
@@ -5256,14 +5408,14 @@
 	if ( wp_is_block_theme() ) {
 		$submenu['themes.php'][] = array( $menu_name, 'edit_theme_options', 'widgets.php' );
 	} else {
-		$submenu['themes.php'][7] = array( $menu_name, 'edit_theme_options', 'widgets.php' );
+		$submenu['themes.php'][8] = array( $menu_name, 'edit_theme_options', 'widgets.php' );
 	}
 
 	ksort( $submenu['themes.php'], SORT_NUMERIC );
 }
 
 /**
- * Flush all output buffers for PHP 5.2.
+ * Flushes all output buffers for PHP 5.2.
  *
  * Make sure all output buffers are flushed before our singletons are destroyed.
  *
@@ -5277,7 +5429,7 @@
 }
 
 /**
- * Load custom DB error or display WordPress DB error.
+ * Loads custom DB error or display WordPress DB error.
  *
  * If a file exists in the wp-content directory named db-error.php, then it will
  * be loaded instead of displaying the WordPress DB error. If it is not found,
@@ -5315,7 +5467,7 @@
 }
 
 /**
- * Convert a value to non-negative integer.
+ * Converts a value to non-negative integer.
  *
  * @since 2.5.0
  *
@@ -5327,11 +5479,10 @@
 }
 
 /**
- * Mark a function as deprecated and inform when it has been used.
- *
- * There is a {@see 'hook deprecated_function_run'} that will be called that can be used
- * to get the backtrace up to what file and function called the deprecated
- * function.
+ * Marks a function as deprecated and inform when it has been used.
+ *
+ * There is a {@see 'deprecated_function_run'} hook that will be called that can be used
+ * to get the backtrace up to what file and function called the deprecated function.
  *
  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  *
@@ -5341,22 +5492,22 @@
  * @since 5.4.0 This function is no longer marked as "private".
  * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE).
  *
- * @param string $function    The function that was called.
- * @param string $version     The version of WordPress that deprecated the function.
- * @param string $replacement Optional. The function that should have been called. Default empty.
- */
-function _deprecated_function( $function, $version, $replacement = '' ) {
+ * @param string $function_name The function that was called.
+ * @param string $version       The version of WordPress that deprecated the function.
+ * @param string $replacement   Optional. The function that should have been called. Default empty string.
+ */
+function _deprecated_function( $function_name, $version, $replacement = '' ) {
 
 	/**
 	 * Fires when a deprecated function is called.
 	 *
 	 * @since 2.5.0
 	 *
-	 * @param string $function    The function that was called.
-	 * @param string $replacement The function that should have been called.
-	 * @param string $version     The version of WordPress that deprecated the function.
+	 * @param string $function_name The function that was called.
+	 * @param string $replacement   The function that should have been called.
+	 * @param string $version       The version of WordPress that deprecated the function.
 	 */
-	do_action( 'deprecated_function_run', $function, $replacement, $version );
+	do_action( 'deprecated_function_run', $function_name, $replacement, $version );
 
 	/**
 	 * Filters whether to trigger an error for deprecated functions.
@@ -5368,49 +5519,39 @@
 	if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
 		if ( function_exists( '__' ) ) {
 			if ( $replacement ) {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP function name, 2: Version number, 3: Alternative function name. */
-						__( 'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
-						$function,
-						$version,
-						$replacement
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP function name, 2: Version number, 3: Alternative function name. */
+					__( 'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+					$function_name,
+					$version,
+					$replacement
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP function name, 2: Version number. */
-						__( 'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
-						$function,
-						$version
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP function name, 2: Version number. */
+					__( 'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+					$function_name,
+					$version
 				);
 			}
 		} else {
 			if ( $replacement ) {
-				trigger_error(
-					sprintf(
-						'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
-						$function,
-						$version,
-						$replacement
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'Function %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
+					$function_name,
+					$version,
+					$replacement
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
-						$function,
-						$version
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'Function %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
+					$function_name,
+					$version
 				);
 			}
 		}
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
 	}
 }
 
@@ -5418,23 +5559,23 @@
  * Marks a constructor as deprecated and informs when it has been used.
  *
  * Similar to _deprecated_function(), but with different strings. Used to
- * remove PHP4 style constructors.
+ * remove PHP4-style constructors.
  *
  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  *
- * This function is to be used in every PHP4 style constructor method that is deprecated.
+ * This function is to be used in every PHP4-style constructor method that is deprecated.
  *
  * @since 4.3.0
  * @since 4.5.0 Added the `$parent_class` parameter.
  * @since 5.4.0 This function is no longer marked as "private".
  * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE).
  *
- * @param string $class        The class containing the deprecated constructor.
+ * @param string $class_name   The class containing the deprecated constructor.
  * @param string $version      The version of WordPress that deprecated the function.
  * @param string $parent_class Optional. The parent class calling the deprecated constructor.
  *                             Default empty string.
  */
-function _deprecated_constructor( $class, $version, $parent_class = '' ) {
+function _deprecated_constructor( $class_name, $version, $parent_class = '' ) {
 
 	/**
 	 * Fires when a deprecated constructor is called.
@@ -5442,11 +5583,11 @@
 	 * @since 4.3.0
 	 * @since 4.5.0 Added the `$parent_class` parameter.
 	 *
-	 * @param string $class        The class containing the deprecated constructor.
+	 * @param string $class_name   The class containing the deprecated constructor.
 	 * @param string $version      The version of WordPress that deprecated the function.
 	 * @param string $parent_class The parent class calling the deprecated constructor.
 	 */
-	do_action( 'deprecated_constructor_run', $class, $version, $parent_class );
+	do_action( 'deprecated_constructor_run', $class_name, $version, $parent_class );
 
 	/**
 	 * Filters whether to trigger an error for deprecated functions.
@@ -5460,63 +5601,128 @@
 	if ( WP_DEBUG && apply_filters( 'deprecated_constructor_trigger_error', true ) ) {
 		if ( function_exists( '__' ) ) {
 			if ( $parent_class ) {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP class name, 2: PHP parent class name, 3: Version number, 4: __construct() method. */
-						__( 'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.' ),
-						$class,
-						$parent_class,
-						$version,
-						'<code>__construct()</code>'
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP class name, 2: PHP parent class name, 3: Version number, 4: __construct() method. */
+					__( 'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.' ),
+					$class_name,
+					$parent_class,
+					$version,
+					'<code>__construct()</code>'
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP class name, 2: Version number, 3: __construct() method. */
-						__( 'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
-						$class,
-						$version,
-						'<code>__construct()</code>'
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP class name, 2: Version number, 3: __construct() method. */
+					__( 'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+					$class_name,
+					$version,
+					'<code>__construct()</code>'
 				);
 			}
 		} else {
 			if ( $parent_class ) {
-				trigger_error(
-					sprintf(
-						'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
-						$class,
-						$parent_class,
-						$version,
-						'<code>__construct()</code>'
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'The called constructor method for %1$s class in %2$s is <strong>deprecated</strong> since version %3$s! Use %4$s instead.',
+					$class_name,
+					$parent_class,
+					$version,
+					'<code>__construct()</code>'
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
-						$class,
-						$version,
-						'<code>__construct()</code>'
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'The called constructor method for %1$s class is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
+					$class_name,
+					$version,
+					'<code>__construct()</code>'
 				);
 			}
 		}
-	}
-
-}
-
-/**
- * Mark a file as deprecated and inform when it has been used.
- *
- * There is a hook {@see 'deprecated_file_included'} that will be called that can be used
- * to get the backtrace up to what file and function included the deprecated
- * file.
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
+	}
+}
+
+/**
+ * Marks a class as deprecated and informs when it has been used.
+ *
+ * There is a {@see 'deprecated_class_run'} hook that will be called that can be used
+ * to get the backtrace up to what file and function called the deprecated class.
+ *
+ * The current behavior is to trigger a user error if `WP_DEBUG` is true.
+ *
+ * This function is to be used in the class constructor for every deprecated class.
+ * See {@see _deprecated_constructor()} for deprecating PHP4-style constructors.
+ *
+ * @since 6.4.0
+ *
+ * @param string $class_name  The name of the class being instantiated.
+ * @param string $version     The version of WordPress that deprecated the class.
+ * @param string $replacement Optional. The class or function that should have been called.
+ *                            Default empty string.
+ */
+function _deprecated_class( $class_name, $version, $replacement = '' ) {
+
+	/**
+	 * Fires when a deprecated class is called.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param string $class_name  The name of the class being instantiated.
+	 * @param string $replacement The class or function that should have been called.
+	 * @param string $version     The version of WordPress that deprecated the class.
+	 */
+	do_action( 'deprecated_class_run', $class_name, $replacement, $version );
+
+	/**
+	 * Filters whether to trigger an error for a deprecated class.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param bool $trigger Whether to trigger an error for a deprecated class. Default true.
+	 */
+	if ( WP_DEBUG && apply_filters( 'deprecated_class_trigger_error', true ) ) {
+		if ( function_exists( '__' ) ) {
+			if ( $replacement ) {
+				$message = sprintf(
+					/* translators: 1: PHP class name, 2: Version number, 3: Alternative class or function name. */
+					__( 'Class %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+					$class_name,
+					$version,
+					$replacement
+				);
+			} else {
+				$message = sprintf(
+					/* translators: 1: PHP class name, 2: Version number. */
+					__( 'Class %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+					$class_name,
+					$version
+				);
+			}
+		} else {
+			if ( $replacement ) {
+				$message = sprintf(
+					'Class %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
+					$class_name,
+					$version,
+					$replacement
+				);
+			} else {
+				$message = sprintf(
+					'Class %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
+					$class_name,
+					$version
+				);
+			}
+		}
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
+	}
+}
+
+/**
+ * Marks a file as deprecated and inform when it has been used.
+ *
+ * There is a {@see 'deprecated_file_included'} hook that will be called that can be used
+ * to get the backtrace up to what file and function included the deprecated file.
  *
  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  *
@@ -5529,8 +5735,8 @@
  * @param string $file        The file that was included.
  * @param string $version     The version of WordPress that deprecated the file.
  * @param string $replacement Optional. The file that should have been included based on ABSPATH.
- *                            Default empty.
- * @param string $message     Optional. A message regarding the change. Default empty.
+ *                            Default empty string.
+ * @param string $message     Optional. A message regarding the change. Default empty string.
  */
 function _deprecated_file( $file, $version, $replacement = '', $message = '' ) {
 
@@ -5558,66 +5764,56 @@
 
 		if ( function_exists( '__' ) ) {
 			if ( $replacement ) {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP file name, 2: Version number, 3: Alternative file name. */
-						__( 'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
-						$file,
-						$version,
-						$replacement
-					) . $message,
-					E_USER_DEPRECATED
-				);
+				$message = sprintf(
+					/* translators: 1: PHP file name, 2: Version number, 3: Alternative file name. */
+					__( 'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+					$file,
+					$version,
+					$replacement
+				) . $message;
 			} else {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP file name, 2: Version number. */
-						__( 'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
-						$file,
-						$version
-					) . $message,
-					E_USER_DEPRECATED
-				);
+				$message = sprintf(
+					/* translators: 1: PHP file name, 2: Version number. */
+					__( 'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+					$file,
+					$version
+				) . $message;
 			}
 		} else {
 			if ( $replacement ) {
-				trigger_error(
-					sprintf(
-						'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
-						$file,
-						$version,
-						$replacement
-					) . $message,
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'File %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.',
+					$file,
+					$version,
+					$replacement
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
-						$file,
-						$version
-					) . $message,
-					E_USER_DEPRECATED
-				);
+				$message = sprintf(
+					'File %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.',
+					$file,
+					$version
+				) . $message;
 			}
 		}
-	}
-}
-/**
- * Mark a function argument as deprecated and inform when it has been used.
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
+	}
+}
+/**
+ * Marks a function argument as deprecated and inform when it has been used.
  *
  * This function is to be used whenever a deprecated function argument is used.
  * Before this function is called, the argument must be checked for whether it was
  * used by comparing it to its default value or evaluating whether it is empty.
+ *
  * For example:
  *
  *     if ( ! empty( $deprecated ) ) {
  *         _deprecated_argument( __FUNCTION__, '3.0.0' );
  *     }
  *
- * There is a hook deprecated_argument_run that will be called that can be used
- * to get the backtrace up to what file and function used the deprecated
- * argument.
+ * There is a {@see 'deprecated_argument_run'} hook that will be called that can be used
+ * to get the backtrace up to what file and function used the deprecated argument.
  *
  * The current behavior is to trigger a user error if WP_DEBUG is true.
  *
@@ -5625,22 +5821,22 @@
  * @since 5.4.0 This function is no longer marked as "private".
  * @since 5.4.0 The error type is now classified as E_USER_DEPRECATED (used to default to E_USER_NOTICE).
  *
- * @param string $function The function that was called.
- * @param string $version  The version of WordPress that deprecated the argument used.
- * @param string $message  Optional. A message regarding the change. Default empty.
- */
-function _deprecated_argument( $function, $version, $message = '' ) {
+ * @param string $function_name The function that was called.
+ * @param string $version       The version of WordPress that deprecated the argument used.
+ * @param string $message       Optional. A message regarding the change. Default empty string.
+ */
+function _deprecated_argument( $function_name, $version, $message = '' ) {
 
 	/**
 	 * Fires when a deprecated argument is called.
 	 *
 	 * @since 3.0.0
 	 *
-	 * @param string $function The function that was called.
-	 * @param string $message  A message regarding the change.
-	 * @param string $version  The version of WordPress that deprecated the argument used.
+	 * @param string $function_name The function that was called.
+	 * @param string $message       A message regarding the change.
+	 * @param string $version       The version of WordPress that deprecated the argument used.
 	 */
-	do_action( 'deprecated_argument_run', $function, $message, $version );
+	do_action( 'deprecated_argument_run', $function_name, $message, $version );
 
 	/**
 	 * Filters whether to trigger an error for deprecated arguments.
@@ -5652,49 +5848,39 @@
 	if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
 		if ( function_exists( '__' ) ) {
 			if ( $message ) {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP function name, 2: Version number, 3: Optional message regarding the change. */
-						__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s' ),
-						$function,
-						$version,
-						$message
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP function name, 2: Version number, 3: Optional message regarding the change. */
+					__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s' ),
+					$function_name,
+					$version,
+					$message
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						/* translators: 1: PHP function name, 2: Version number. */
-						__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
-						$function,
-						$version
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					/* translators: 1: PHP function name, 2: Version number. */
+					__( 'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+					$function_name,
+					$version
 				);
 			}
 		} else {
 			if ( $message ) {
-				trigger_error(
-					sprintf(
-						'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s',
-						$function,
-						$version,
-						$message
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s',
+					$function_name,
+					$version,
+					$message
 				);
 			} else {
-				trigger_error(
-					sprintf(
-						'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.',
-						$function,
-						$version
-					),
-					E_USER_DEPRECATED
+				$message = sprintf(
+					'Function %1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.',
+					$function_name,
+					$version
 				);
 			}
 		}
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
 	}
 }
 
@@ -5715,7 +5901,7 @@
  *
  * @param string $hook        The hook that was used.
  * @param string $version     The version of WordPress that deprecated the hook.
- * @param string $replacement Optional. The hook that should have been used. Default empty.
+ * @param string $replacement Optional. The hook that should have been used. Default empty string.
  * @param string $message     Optional. A message regarding the change. Default empty.
  */
 function _deprecated_hook( $hook, $version, $replacement = '', $message = '' ) {
@@ -5743,71 +5929,66 @@
 		$message = empty( $message ) ? '' : ' ' . $message;
 
 		if ( $replacement ) {
-			trigger_error(
-				sprintf(
-					/* translators: 1: WordPress hook name, 2: Version number, 3: Alternative hook name. */
-					__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
-					$hook,
-					$version,
-					$replacement
-				) . $message,
-				E_USER_DEPRECATED
-			);
+			$message = sprintf(
+				/* translators: 1: WordPress hook name, 2: Version number, 3: Alternative hook name. */
+				__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ),
+				$hook,
+				$version,
+				$replacement
+			) . $message;
 		} else {
-			trigger_error(
-				sprintf(
-					/* translators: 1: WordPress hook name, 2: Version number. */
-					__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
-					$hook,
-					$version
-				) . $message,
-				E_USER_DEPRECATED
-			);
-		}
-	}
-}
-
-/**
- * Mark something as being incorrectly called.
- *
- * There is a hook {@see 'doing_it_wrong_run'} that will be called that can be used
- * to get the backtrace up to what file and function called the deprecated
- * function.
+			$message = sprintf(
+				/* translators: 1: WordPress hook name, 2: Version number. */
+				__( 'Hook %1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ),
+				$hook,
+				$version
+			) . $message;
+		}
+
+		wp_trigger_error( '', $message, E_USER_DEPRECATED );
+	}
+}
+
+/**
+ * Marks something as being incorrectly called.
+ *
+ * There is a {@see 'doing_it_wrong_run'} hook that will be called that can be used
+ * to get the backtrace up to what file and function called the deprecated function.
  *
  * The current behavior is to trigger a user error if `WP_DEBUG` is true.
  *
  * @since 3.1.0
  * @since 5.4.0 This function is no longer marked as "private".
  *
- * @param string $function The function that was called.
- * @param string $message  A message explaining what has been done incorrectly.
- * @param string $version  The version of WordPress where the message was added.
- */
-function _doing_it_wrong( $function, $message, $version ) {
+ * @param string $function_name The function that was called.
+ * @param string $message       A message explaining what has been done incorrectly.
+ * @param string $version       The version of WordPress where the message was added.
+ */
+function _doing_it_wrong( $function_name, $message, $version ) {
 
 	/**
 	 * Fires when the given function is being used incorrectly.
 	 *
 	 * @since 3.1.0
 	 *
-	 * @param string $function The function that was called.
-	 * @param string $message  A message explaining what has been done incorrectly.
-	 * @param string $version  The version of WordPress where the message was added.
+	 * @param string $function_name The function that was called.
+	 * @param string $message       A message explaining what has been done incorrectly.
+	 * @param string $version       The version of WordPress where the message was added.
 	 */
-	do_action( 'doing_it_wrong_run', $function, $message, $version );
+	do_action( 'doing_it_wrong_run', $function_name, $message, $version );
 
 	/**
 	 * Filters whether to trigger an error for _doing_it_wrong() calls.
 	 *
 	 * @since 3.1.0
-	 * @since 5.1.0 Added the $function, $message and $version parameters.
-	 *
-	 * @param bool   $trigger  Whether to trigger the error for _doing_it_wrong() calls. Default true.
-	 * @param string $function The function that was called.
-	 * @param string $message  A message explaining what has been done incorrectly.
-	 * @param string $version  The version of WordPress where the message was added.
+	 * @since 5.1.0 Added the $function_name, $message and $version parameters.
+	 *
+	 * @param bool   $trigger       Whether to trigger the error for _doing_it_wrong() calls. Default true.
+	 * @param string $function_name The function that was called.
+	 * @param string $message       A message explaining what has been done incorrectly.
+	 * @param string $version       The version of WordPress where the message was added.
 	 */
-	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true, $function, $message, $version ) ) {
+	if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true, $function_name, $message, $version ) ) {
 		if ( function_exists( '__' ) ) {
 			if ( $version ) {
 				/* translators: %s: Version number. */
@@ -5817,18 +5998,15 @@
 			$message .= ' ' . sprintf(
 				/* translators: %s: Documentation URL. */
 				__( 'Please see <a href="%s">Debugging in WordPress</a> for more information.' ),
-				__( 'https://wordpress.org/support/article/debugging-in-wordpress/' )
+				__( 'https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/' )
 			);
 
-			trigger_error(
-				sprintf(
-					/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: WordPress version number. */
-					__( 'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s' ),
-					$function,
-					$message,
-					$version
-				),
-				E_USER_NOTICE
+			$message = sprintf(
+				/* translators: Developer debugging message. 1: PHP function name, 2: Explanatory message, 3: WordPress version number. */
+				__( 'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s' ),
+				$function_name,
+				$message,
+				$version
 			);
 		} else {
 			if ( $version ) {
@@ -5837,24 +6015,78 @@
 
 			$message .= sprintf(
 				' Please see <a href="%s">Debugging in WordPress</a> for more information.',
-				'https://wordpress.org/support/article/debugging-in-wordpress/'
+				'https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/'
+			);
+
+			$message = sprintf(
+				'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s',
+				$function_name,
+				$message,
+				$version
 			);
-
-			trigger_error(
-				sprintf(
-					'Function %1$s was called <strong>incorrectly</strong>. %2$s %3$s',
-					$function,
-					$message,
-					$version
-				),
-				E_USER_NOTICE
-			);
-		}
-	}
-}
-
-/**
- * Is the server running earlier than 1.5.0 version of lighttpd?
+		}
+
+		wp_trigger_error( '', $message );
+	}
+}
+
+/**
+ * Generates a user-level error/warning/notice/deprecation message.
+ *
+ * Generates the message when `WP_DEBUG` is true.
+ *
+ * @since 6.4.0
+ *
+ * @param string $function_name The function that triggered the error.
+ * @param string $message       The message explaining the error.
+ *                              The message can contain allowed HTML 'a' (with href), 'code',
+ *                              'br', 'em', and 'strong' tags and http or https protocols.
+ *                              If it contains other HTML tags or protocols, the message should be escaped
+ *                              before passing to this function to avoid being stripped {@see wp_kses()}.
+ * @param int    $error_level   Optional. The designated error type for this error.
+ *                              Only works with E_USER family of constants. Default E_USER_NOTICE.
+ */
+function wp_trigger_error( $function_name, $message, $error_level = E_USER_NOTICE ) {
+
+	// Bail out if WP_DEBUG is not turned on.
+	if ( ! WP_DEBUG ) {
+		return;
+	}
+
+	/**
+	 * Fires when the given function triggers a user-level error/warning/notice/deprecation message.
+	 *
+	 * Can be used for debug backtracking.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param string $function_name The function that was called.
+	 * @param string $message       A message explaining what has been done incorrectly.
+	 * @param int    $error_level   The designated error type for this error.
+	 */
+	do_action( 'wp_trigger_error_run', $function_name, $message, $error_level );
+
+	if ( ! empty( $function_name ) ) {
+		$message = sprintf( '%s(): %s', $function_name, $message );
+	}
+
+	$message = wp_kses(
+		$message,
+		array(
+			'a'      => array( 'href' => true ),
+			'br'     => array(),
+			'code'   => array(),
+			'em'     => array(),
+			'strong' => array(),
+		),
+		array( 'http', 'https' )
+	);
+
+	trigger_error( $message, $error_level );
+}
+
+/**
+ * Determines whether the server is running an earlier than 1.5.0 version of lighttpd.
  *
  * @since 2.5.0
  *
@@ -5864,46 +6096,55 @@
 	$server_parts    = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '' );
 	$server_parts[1] = isset( $server_parts[1] ) ? $server_parts[1] : '';
 
-	return ( 'lighttpd' === $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' ) );
-}
-
-/**
- * Does the specified module exist in the Apache config?
+	return ( 'lighttpd' === $server_parts[0] && -1 === version_compare( $server_parts[1], '1.5.0' ) );
+}
+
+/**
+ * Determines whether the specified module exist in the Apache config.
  *
  * @since 2.5.0
  *
  * @global bool $is_apache
  *
- * @param string $mod     The module, e.g. mod_rewrite.
- * @param bool   $default Optional. The default return value if the module is not found. Default false.
+ * @param string $mod           The module, e.g. mod_rewrite.
+ * @param bool   $default_value Optional. The default return value if the module is not found. Default false.
  * @return bool Whether the specified module is loaded.
  */
-function apache_mod_loaded( $mod, $default = false ) {
+function apache_mod_loaded( $mod, $default_value = false ) {
 	global $is_apache;
 
 	if ( ! $is_apache ) {
 		return false;
 	}
 
+	$loaded_mods = array();
+
 	if ( function_exists( 'apache_get_modules' ) ) {
-		$mods = apache_get_modules();
-		if ( in_array( $mod, $mods, true ) ) {
+		$loaded_mods = apache_get_modules();
+
+		if ( in_array( $mod, $loaded_mods, true ) ) {
 			return true;
 		}
-	} elseif ( function_exists( 'phpinfo' ) && false === strpos( ini_get( 'disable_functions' ), 'phpinfo' ) ) {
-			ob_start();
-			phpinfo( 8 );
-			$phpinfo = ob_get_clean();
-		if ( false !== strpos( $phpinfo, $mod ) ) {
+	}
+
+	if ( empty( $loaded_mods )
+		&& function_exists( 'phpinfo' )
+		&& ! str_contains( ini_get( 'disable_functions' ), 'phpinfo' )
+	) {
+		ob_start();
+		phpinfo( INFO_MODULES );
+		$phpinfo = ob_get_clean();
+
+		if ( str_contains( $phpinfo, $mod ) ) {
 			return true;
 		}
 	}
 
-	return $default;
-}
-
-/**
- * Check if IIS 7+ supports pretty permalinks.
+	return $default_value;
+}
+
+/**
+ * Checks if IIS 7+ supports pretty permalinks.
  *
  * @since 2.8.0
  *
@@ -5920,7 +6161,7 @@
 		 * easily update the xml configuration file, hence we just bail out and tell user that
 		 * pretty permalinks cannot be used.
 		 *
-		 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
+		 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the website. When
 		 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
 		 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
 		 * via ISAPI then pretty permalinks will not work.
@@ -5950,7 +6191,7 @@
  * @since 1.2.0
  *
  * @param string   $file          File path.
- * @param string[] $allowed_files Optional. Array of allowed files.
+ * @param string[] $allowed_files Optional. Array of allowed files. Default empty array.
  * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
  */
 function validate_file( $file, $allowed_files = array() ) {
@@ -5958,6 +6199,11 @@
 		return 0;
 	}
 
+	// Normalize path for Windows servers.
+	$file = wp_normalize_path( $file );
+	// Normalize path for $allowed_files as well so it's an apples to apples comparison.
+	$allowed_files = array_map( 'wp_normalize_path', $allowed_files );
+
 	// `../` on its own is not allowed:
 	if ( '../' === $file ) {
 		return 1;
@@ -5969,7 +6215,7 @@
 	}
 
 	// `../` which does not occur at the end of the path is not allowed:
-	if ( false !== strpos( $file, '../' ) && '../' !== mb_substr( $file, -3, 3 ) ) {
+	if ( str_contains( $file, '../' ) && '../' !== mb_substr( $file, -3, 3 ) ) {
 		return 1;
 	}
 
@@ -5987,7 +6233,7 @@
 }
 
 /**
- * Whether to force SSL used for the Administration Screens.
+ * Determines whether to force SSL used for the Administration Screens.
  *
  * @since 2.6.0
  *
@@ -6007,7 +6253,7 @@
 }
 
 /**
- * Guess the URL for the site.
+ * Guesses the URL for the site.
  *
  * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
  * directory.
@@ -6024,8 +6270,8 @@
 		$script_filename_dir = dirname( $_SERVER['SCRIPT_FILENAME'] );
 
 		// The request is for the admin.
-		if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false ) {
-			$path = preg_replace( '#/(wp-admin/.*|wp-login.php)#i', '', $_SERVER['REQUEST_URI'] );
+		if ( str_contains( $_SERVER['REQUEST_URI'], 'wp-admin' ) || str_contains( $_SERVER['REQUEST_URI'], 'wp-login.php' ) ) {
+			$path = preg_replace( '#/(wp-admin/?.*|wp-login\.php.*)#i', '', $_SERVER['REQUEST_URI'] );
 
 			// The request is for a file in ABSPATH.
 		} elseif ( $script_filename_dir . '/' === $abspath_fix ) {
@@ -6033,12 +6279,12 @@
 			$path = preg_replace( '#/[^/]*$#i', '', $_SERVER['PHP_SELF'] );
 
 		} else {
-			if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
+			if ( str_contains( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
 				// Request is hitting a file inside ABSPATH.
 				$directory = str_replace( ABSPATH, '', $script_filename_dir );
 				// Strip off the subdirectory, and any file/query params.
 				$path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '', $_SERVER['REQUEST_URI'] );
-			} elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
+			} elseif ( str_contains( $abspath_fix, $script_filename_dir ) ) {
 				// Request is hitting a file above ABSPATH.
 				$subdirectory = substr( $abspath_fix, strpos( $abspath_fix, $script_filename_dir ) + strlen( $script_filename_dir ) );
 				// Strip off any file/query params from the path, appending the subdirectory to the installation.
@@ -6056,7 +6302,7 @@
 }
 
 /**
- * Temporarily suspend cache additions.
+ * Temporarily suspends cache additions.
  *
  * Stops more data being added to the cache, but still allows cache retrieval.
  * This is useful for actions, such as imports, when a lot of data would otherwise
@@ -6068,7 +6314,8 @@
  * @since 3.3.0
  *
  * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
- * @return bool The current suspend setting
+ *                      Defaults to not changing the current setting.
+ * @return bool The current suspend setting.
  */
 function wp_suspend_cache_addition( $suspend = null ) {
 	static $_suspend = false;
@@ -6081,7 +6328,7 @@
 }
 
 /**
- * Suspend cache invalidation.
+ * Suspends cache invalidation.
  *
  * Turns cache invalidation on and off. Useful during imports where you don't want to do
  * invalidations every time a post is inserted. Callers must be sure that what they are
@@ -6103,7 +6350,7 @@
 }
 
 /**
- * Determine whether a site is the main site of the current network.
+ * Determines whether a site is the main site of the current network.
  *
  * @since 3.0.0
  * @since 4.9.0 The `$network_id` parameter was added.
@@ -6151,7 +6398,7 @@
 }
 
 /**
- * Determine whether a network is the main network of the Multisite installation.
+ * Determines whether a network is the main network of the Multisite installation.
  *
  * @since 3.7.0
  *
@@ -6173,7 +6420,7 @@
 }
 
 /**
- * Get the main network ID.
+ * Gets the main network ID.
  *
  * @since 4.3.0
  *
@@ -6212,41 +6459,6 @@
 }
 
 /**
- * Determine whether global terms are enabled.
- *
- * @since 3.0.0
- *
- * @return bool True if multisite and global terms enabled.
- */
-function global_terms_enabled() {
-	if ( ! is_multisite() ) {
-		return false;
-	}
-
-	static $global_terms = null;
-	if ( is_null( $global_terms ) ) {
-
-		/**
-		 * Filters whether global terms are enabled.
-		 *
-		 * Returning a non-null value from the filter will effectively short-circuit the function
-		 * and return the value of the 'global_terms_enabled' site option instead.
-		 *
-		 * @since 3.0.0
-		 *
-		 * @param null $enabled Whether global terms are enabled.
-		 */
-		$filter = apply_filters( 'global_terms_enabled', null );
-		if ( ! is_null( $filter ) ) {
-			$global_terms = (bool) $filter;
-		} else {
-			$global_terms = (bool) get_site_option( 'global_terms_enabled', false );
-		}
-	}
-	return $global_terms;
-}
-
-/**
  * Determines whether site meta is enabled.
  *
  * This function checks whether the 'blogmeta' database table exists. The result is saved as
@@ -6279,7 +6491,7 @@
 }
 
 /**
- * gmt_offset modification for smart timezone handling.
+ * Modifies gmt_offset for smart timezone handling.
  *
  * Overrides the gmt_offset option if we have a timezone_string available.
  *
@@ -6298,6 +6510,7 @@
 	if ( false === $timezone_object || false === $datetime_object ) {
 		return false;
 	}
+
 	return round( timezone_offset_get( $timezone_object, $datetime_object ) / HOUR_IN_SECONDS, 2 );
 }
 
@@ -6315,36 +6528,45 @@
 	// Don't use translated versions of Etc.
 	if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) {
 		// Make the order of these more like the old dropdown.
-		if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) {
+		if ( str_starts_with( $a['city'], 'GMT+' ) && str_starts_with( $b['city'], 'GMT+' ) ) {
 			return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) );
 		}
+
 		if ( 'UTC' === $a['city'] ) {
-			if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) {
+			if ( str_starts_with( $b['city'], 'GMT+' ) ) {
 				return 1;
 			}
+
 			return -1;
 		}
+
 		if ( 'UTC' === $b['city'] ) {
-			if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) {
+			if ( str_starts_with( $a['city'], 'GMT+' ) ) {
 				return -1;
 			}
+
 			return 1;
 		}
+
 		return strnatcasecmp( $a['city'], $b['city'] );
 	}
-	if ( $a['t_continent'] == $b['t_continent'] ) {
-		if ( $a['t_city'] == $b['t_city'] ) {
+
+	if ( $a['t_continent'] === $b['t_continent'] ) {
+		if ( $a['t_city'] === $b['t_city'] ) {
 			return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] );
 		}
+
 		return strnatcasecmp( $a['t_city'], $b['t_city'] );
 	} else {
 		// Force Etc to the bottom of the list.
 		if ( 'Etc' === $a['continent'] ) {
 			return 1;
 		}
+
 		if ( 'Etc' === $b['continent'] ) {
 			return -1;
 		}
+
 		return strnatcasecmp( $a['t_continent'], $b['t_continent'] );
 	}
 }
@@ -6368,13 +6590,15 @@
 	if ( ! $mo_loaded || $locale !== $locale_loaded ) {
 		$locale_loaded = $locale ? $locale : get_locale();
 		$mofile        = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
-		unload_textdomain( 'continents-cities' );
-		load_textdomain( 'continents-cities', $mofile );
+		unload_textdomain( 'continents-cities', true );
+		load_textdomain( 'continents-cities', $mofile, $locale_loaded );
 		$mo_loaded = true;
 	}
 
-	$zonen = array();
-	foreach ( timezone_identifiers_list() as $zone ) {
+	$tz_identifiers = timezone_identifiers_list();
+	$zonen          = array();
+
+	foreach ( $tz_identifiers as $zone ) {
 		$zone = explode( '/', $zone );
 		if ( ! in_array( $zone[0], $continents, true ) ) {
 			continue;
@@ -6409,6 +6633,13 @@
 		$structure[] = '<option selected="selected" value="">' . __( 'Select a city' ) . '</option>';
 	}
 
+	// If this is a deprecated, but valid, timezone string, display it at the top of the list as-is.
+	if ( in_array( $selected_zone, $tz_identifiers, true ) === false
+		&& in_array( $selected_zone, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true )
+	) {
+		$structure[] = '<option selected="selected" value="' . esc_attr( $selected_zone ) . '">' . esc_html( $selected_zone ) . '</option>';
+	}
+
 	foreach ( $zonen as $key => $zone ) {
 		// Build value in an array to join later.
 		$value = array( $zone['continent'] );
@@ -6542,7 +6773,7 @@
 }
 
 /**
- * Strip close comment and close php tags from file headers used by WP.
+ * Strips close comment and close php tags from file headers used by WP.
  *
  * @since 2.8.0
  * @access private
@@ -6557,7 +6788,7 @@
 }
 
 /**
- * Permanently delete comments or posts of any type that have held a status
+ * Permanently deletes comments or posts of any type that have held a status
  * of 'trash' for the number of days defined in EMPTY_TRASH_DAYS.
  *
  * The default value of `EMPTY_TRASH_DAYS` is 30 (days).
@@ -6609,7 +6840,7 @@
 }
 
 /**
- * Retrieve metadata from a file.
+ * Retrieves metadata from a file.
  *
  * Searches for metadata in the first 8 KB of a file, such as a plugin or theme.
  * Each piece of metadata must be on its own line. Fields can not span multiple
@@ -6625,7 +6856,7 @@
  * @param string $file            Absolute path to the file.
  * @param array  $default_headers List of headers, in the format `array( 'HeaderKey' => 'Header Name' )`.
  * @param string $context         Optional. If specified adds filter hook {@see 'extra_$context_headers'}.
- *                                Default empty.
+ *                                Default empty string.
  * @return string[] Array of file header values keyed by header name.
  */
 function get_file_data( $file, $default_headers, $context = '' ) {
@@ -6753,7 +6984,7 @@
 }
 
 /**
- * Send a HTTP header to disable content type sniffing in browsers which support it.
+ * Sends a HTTP header to disable content type sniffing in browsers which support it.
  *
  * @since 3.0.0
  *
@@ -6765,7 +6996,7 @@
 }
 
 /**
- * Return a MySQL expression for selecting the week number based on the start_of_week option.
+ * Returns a MySQL expression for selecting the week number based on the start_of_week option.
  *
  * @ignore
  * @since 3.0.0
@@ -6791,7 +7022,7 @@
 }
 
 /**
- * Find hierarchy loops using a callback function that maps object IDs to parent IDs.
+ * Finds hierarchy loops using a callback function that maps object IDs to parent IDs.
  *
  * @since 3.1.0
  * @access private
@@ -6799,8 +7030,8 @@
  * @param callable $callback      Function that accepts ( ID, $callback_args ) and outputs parent_ID.
  * @param int      $start         The ID to start the loop check at.
  * @param int      $start_parent  The parent_ID of $start to use instead of calling $callback( $start ).
- *                                Use null to always use $callback
- * @param array    $callback_args Optional. Additional arguments to send to $callback.
+ *                                Use null to always use $callback.
+ * @param array    $callback_args Optional. Additional arguments to send to $callback. Default empty array.
  * @return array IDs of all members of loop.
  */
 function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) {
@@ -6815,7 +7046,7 @@
 }
 
 /**
- * Use the "The Tortoise and the Hare" algorithm to detect loops.
+ * Uses the "The Tortoise and the Hare" algorithm to detect loops.
  *
  * For every step of the algorithm, the hare takes two steps and the tortoise one.
  * If the hare ever laps the tortoise, there must be a loop.
@@ -6840,8 +7071,7 @@
 	$evanescent_hare = $start;
 	$return          = array();
 
-	// Set evanescent_hare to one past hare.
-	// Increment hare two steps.
+	// Set evanescent_hare to one past hare. Increment hare two steps.
 	while (
 		$tortoise
 	&&
@@ -6856,7 +7086,7 @@
 		}
 
 		// Tortoise got lapped - must be a loop.
-		if ( $tortoise == $evanescent_hare || $tortoise == $hare ) {
+		if ( $tortoise === $evanescent_hare || $tortoise === $hare ) {
 			return $_return_loop ? $return : $tortoise;
 		}
 
@@ -6868,7 +7098,7 @@
 }
 
 /**
- * Send a HTTP header to limit rendering of pages to same origin iframes.
+ * Sends a HTTP header to limit rendering of pages to same origin iframes.
  *
  * @since 3.1.3
  *
@@ -6879,7 +7109,7 @@
 }
 
 /**
- * Retrieve a list of protocols to allow in HTML attributes.
+ * Retrieves a list of protocols to allow in HTML attributes.
  *
  * @since 3.3.0
  * @since 4.3.0 Added 'webcal' to the protocols array.
@@ -6940,7 +7170,7 @@
 	$trace       = debug_backtrace( false );
 	$caller      = array();
 	$check_class = ! is_null( $ignore_class );
-	$skip_frames++; // Skip this function.
+	++$skip_frames; // Skip this function.
 
 	if ( ! isset( $truncate_paths ) ) {
 		$truncate_paths = array(
@@ -6951,9 +7181,9 @@
 
 	foreach ( $trace as $call ) {
 		if ( $skip_frames > 0 ) {
-			$skip_frames--;
+			--$skip_frames;
 		} elseif ( isset( $call['class'] ) ) {
-			if ( $check_class && $ignore_class == $call['class'] ) {
+			if ( $check_class && $ignore_class === $call['class'] ) {
 				continue; // Filter out calls.
 			}
 
@@ -6977,21 +7207,28 @@
 }
 
 /**
- * Retrieve IDs that are not already present in the cache.
+ * Retrieves IDs that are not already present in the cache.
  *
  * @since 3.4.0
- * @access private
- *
- * @param int[]  $object_ids Array of IDs.
- * @param string $cache_key  The cache bucket to check against.
+ * @since 6.1.0 This function is no longer marked as "private".
+ *
+ * @param int[]  $object_ids  Array of IDs.
+ * @param string $cache_group The cache group to check against.
  * @return int[] Array of IDs not present in the cache.
  */
-function _get_non_cached_ids( $object_ids, $cache_key ) {
+function _get_non_cached_ids( $object_ids, $cache_group ) {
+	$object_ids = array_filter( $object_ids, '_validate_cache_id' );
+	$object_ids = array_unique( array_map( 'intval', $object_ids ), SORT_NUMERIC );
+
+	if ( empty( $object_ids ) ) {
+		return array();
+	}
+
 	$non_cached_ids = array();
-	$cache_values   = wp_cache_get_multiple( $object_ids, $cache_key );
+	$cache_values   = wp_cache_get_multiple( $object_ids, $cache_group );
 
 	foreach ( $cache_values as $id => $value ) {
-		if ( ! $value ) {
+		if ( false === $value ) {
 			$non_cached_ids[] = (int) $id;
 		}
 	}
@@ -7000,7 +7237,35 @@
 }
 
 /**
- * Test if the current device has the capability to upload files.
+ * Checks whether the given cache ID is either an integer or an integer-like string.
+ *
+ * Both `16` and `"16"` are considered valid, other numeric types and numeric strings
+ * (`16.3` and `"16.3"`) are considered invalid.
+ *
+ * @since 6.3.0
+ *
+ * @param mixed $object_id The cache ID to validate.
+ * @return bool Whether the given $object_id is a valid cache ID.
+ */
+function _validate_cache_id( $object_id ) {
+	/*
+	 * filter_var() could be used here, but the `filter` PHP extension
+	 * is considered optional and may not be available.
+	 */
+	if ( is_int( $object_id )
+		|| ( is_string( $object_id ) && (string) (int) $object_id === $object_id ) ) {
+		return true;
+	}
+
+	/* translators: %s: The type of the given object ID. */
+	$message = sprintf( __( 'Object ID must be an integer, %s given.' ), gettype( $object_id ) );
+	_doing_it_wrong( '_get_non_cached_ids', $message, '6.3.0' );
+
+	return false;
+}
+
+/**
+ * Tests if the current device has the capability to upload files.
  *
  * @since 3.4.0
  * @access private
@@ -7014,9 +7279,9 @@
 
 	$ua = $_SERVER['HTTP_USER_AGENT'];
 
-	if ( strpos( $ua, 'iPhone' ) !== false
-		|| strpos( $ua, 'iPad' ) !== false
-		|| strpos( $ua, 'iPod' ) !== false ) {
+	if ( str_contains( $ua, 'iPhone' )
+		|| str_contains( $ua, 'iPad' )
+		|| str_contains( $ua, 'iPod' ) ) {
 			return preg_match( '#OS ([\d_]+) like Mac OS X#', $ua, $version ) && version_compare( $version[1], '6', '>=' );
 	}
 
@@ -7024,7 +7289,7 @@
 }
 
 /**
- * Test if a given path is a stream URL
+ * Tests if a given path is a stream URL
  *
  * @since 3.5.0
  *
@@ -7045,7 +7310,7 @@
 }
 
 /**
- * Test if the supplied date is valid for the Gregorian calendar.
+ * Tests if the supplied date is valid for the Gregorian calendar.
  *
  * @since 3.5.0
  *
@@ -7070,7 +7335,7 @@
 }
 
 /**
- * Load the auth check for monitoring whether the user is still logged in.
+ * Loads the auth check for monitoring whether the user is still logged in.
  *
  * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
  *
@@ -7114,14 +7379,14 @@
 }
 
 /**
- * Output the HTML that shows the wp-login dialog when the user is no longer logged in.
+ * Outputs the HTML that shows the wp-login dialog when the user is no longer logged in.
  *
  * @since 3.6.0
  */
 function wp_auth_check_html() {
 	$login_url      = wp_login_url();
 	$current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
-	$same_domain    = ( strpos( $login_url, $current_domain ) === 0 );
+	$same_domain    = str_starts_with( $login_url, $current_domain );
 
 	/**
 	 * Filters whether the authentication check originated at the same domain.
@@ -7137,7 +7402,12 @@
 	<div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
 	<div id="wp-auth-check-bg"></div>
 	<div id="wp-auth-check">
-	<button type="button" class="wp-auth-check-close button-link"><span class="screen-reader-text"><?php _e( 'Close dialog' ); ?></span></button>
+	<button type="button" class="wp-auth-check-close button-link"><span class="screen-reader-text">
+		<?php
+		/* translators: Hidden accessibility text. */
+		_e( 'Close dialog' );
+		?>
+	</span></button>
 	<?php
 
 	if ( $same_domain ) {
@@ -7165,7 +7435,7 @@
 }
 
 /**
- * Check whether a user is still logged in, for the heartbeat.
+ * Checks whether a user is still logged in, for the heartbeat.
  *
  * Send a result that shows a log-in box if the user is no longer logged in,
  * or if their cookie is within the grace period.
@@ -7183,7 +7453,7 @@
 }
 
 /**
- * Return RegEx body to liberally match an opening HTML tag.
+ * Returns RegEx body to liberally match an opening HTML tag.
  *
  * Matches an opening HTML tag that:
  * 1. Is self-closing or
@@ -7206,7 +7476,41 @@
 }
 
 /**
- * Retrieve a canonical form of the provided charset appropriate for passing to PHP
+ * Indicates if a given slug for a character set represents the UTF-8
+ * text encoding. If not provided, examines the current blog's charset.
+ *
+ * A charset is considered to represent UTF-8 if it is a case-insensitive
+ * match of "UTF-8" with or without the hyphen.
+ *
+ * Example:
+ *
+ *     true  === is_utf8_charset( 'UTF-8' );
+ *     true  === is_utf8_charset( 'utf8' );
+ *     false === is_utf8_charset( 'latin1' );
+ *     false === is_utf8_charset( 'UTF 8' );
+ *
+ *     // Only strings match.
+ *     false === is_utf8_charset( [ 'charset' => 'utf-8' ] );
+ *
+ *     // Without a given charset, it depends on the site option "blog_charset".
+ *     $is_utf8 = is_utf8_charset();
+ *
+ * @since 6.6.0
+ * @since 6.6.1 A wrapper for _is_utf8_charset
+ *
+ * @see _is_utf8_charset
+ *
+ * @param string|null $blog_charset Optional. Slug representing a text character encoding, or "charset".
+ *                                  E.g. "UTF-8", "Windows-1252", "ISO-8859-1", "SJIS".
+ *                                  Default value is to infer from "blog_charset" option.
+ * @return bool Whether the slug represents the UTF-8 encoding.
+ */
+function is_utf8_charset( $blog_charset = null ) {
+	return _is_utf8_charset( $blog_charset ?? get_option( 'blog_charset' ) );
+}
+
+/**
+ * Retrieves a canonical form of the provided charset appropriate for passing to PHP
  * functions such as htmlspecialchars() and charset HTML attributes.
  *
  * @since 3.6.0
@@ -7214,17 +7518,27 @@
  *
  * @see https://core.trac.wordpress.org/ticket/23688
  *
- * @param string $charset A charset name.
+ * @param string $charset A charset name, e.g. "UTF-8", "Windows-1252", "SJIS".
  * @return string The canonical form of the charset.
  */
 function _canonical_charset( $charset ) {
-	if ( 'utf-8' === strtolower( $charset ) || 'utf8' === strtolower( $charset ) ) {
-
+	if ( is_utf8_charset( $charset ) ) {
 		return 'UTF-8';
 	}
 
-	if ( 'iso-8859-1' === strtolower( $charset ) || 'iso8859-1' === strtolower( $charset ) ) {
-
+	/*
+	 * Normalize the ISO-8859-1 family of languages.
+	 *
+	 * This is not required for htmlspecialchars(), as it properly recognizes all of
+	 * the input character sets that here are transformed into "ISO-8859-1".
+	 *
+	 * @todo Should this entire check be removed since it's not required for the stated purpose?
+	 * @todo Should WordPress transform other potential charset equivalents, such as "latin1"?
+	 */
+	if (
+		( 0 === strcasecmp( 'iso-8859-1', $charset ) ) ||
+		( 0 === strcasecmp( 'iso8859-1', $charset ) )
+	) {
 		return 'ISO-8859-1';
 	}
 
@@ -7232,7 +7546,7 @@
 }
 
 /**
- * Set the mbstring internal encoding to a binary safe encoding when func_overload
+ * Sets the mbstring internal encoding to a binary safe encoding when func_overload
  * is enabled.
  *
  * When mbstring.func_overload is in use for multi-byte encodings, the results from
@@ -7285,7 +7599,7 @@
 }
 
 /**
- * Reset the mbstring internal encoding to a users previously set encoding.
+ * Resets the mbstring internal encoding to a users previously set encoding.
  *
  * @see mbstring_binary_safe_encoding()
  *
@@ -7296,29 +7610,29 @@
 }
 
 /**
- * Filter/validate a variable as a boolean.
- *
- * Alternative to `filter_var( $var, FILTER_VALIDATE_BOOLEAN )`.
+ * Filters/validates a variable as a boolean.
+ *
+ * Alternative to `filter_var( $value, FILTER_VALIDATE_BOOLEAN )`.
  *
  * @since 4.0.0
  *
- * @param mixed $var Boolean value to validate.
+ * @param mixed $value Boolean value to validate.
  * @return bool Whether the value is validated.
  */
-function wp_validate_boolean( $var ) {
-	if ( is_bool( $var ) ) {
-		return $var;
-	}
-
-	if ( is_string( $var ) && 'false' === strtolower( $var ) ) {
+function wp_validate_boolean( $value ) {
+	if ( is_bool( $value ) ) {
+		return $value;
+	}
+
+	if ( is_string( $value ) && 'false' === strtolower( $value ) ) {
 		return false;
 	}
 
-	return (bool) $var;
-}
-
-/**
- * Delete a file
+	return (bool) $value;
+}
+
+/**
+ * Deletes a file.
  *
  * @since 4.2.0
  *
@@ -7364,7 +7678,7 @@
 		$real_directory = wp_normalize_path( $real_directory );
 	}
 
-	if ( false === $real_file || false === $real_directory || strpos( $real_file, trailingslashit( $real_directory ) ) !== 0 ) {
+	if ( false === $real_file || false === $real_directory || ! str_starts_with( $real_file, trailingslashit( $real_directory ) ) ) {
 		return false;
 	}
 
@@ -7374,7 +7688,7 @@
 }
 
 /**
- * Outputs a small JS snippet on preview tabs/windows to remove `window.name` on unload.
+ * Outputs a small JS snippet on preview tabs/windows to remove `window.name` when a user is navigating to another page.
  *
  * This prevents reusing the same tab for a preview when the user has navigated away.
  *
@@ -7392,6 +7706,7 @@
 	// Has to match the window name used in post_submit_meta_box().
 	$name = 'wp-preview-' . (int) $post->ID;
 
+	ob_start();
 	?>
 	<script>
 	( function() {
@@ -7402,11 +7717,12 @@
 		}
 
 		if ( window.addEventListener ) {
-			window.addEventListener( 'unload', function() { window.name = ''; }, false );
+			window.addEventListener( 'pagehide', function() { window.name = ''; } );
 		}
 	}());
 	</script>
 	<?php
+	wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
 }
 
 /**
@@ -7435,7 +7751,7 @@
  * @since 4.6.0
  *
  * @param string $context Optional. Context in which the function is called. Accepts either 'admin',
- *                        'image', or an arbitrary other context. If an arbitrary context is passed,
+ *                        'image', 'cron', or an arbitrary other context. If an arbitrary context is passed,
  *                        the similarly arbitrary {@see '$context_memory_limit'} filter will be
  *                        invoked. Default 'admin'.
  * @return int|string|false The limit that was set or false on failure.
@@ -7487,7 +7803,7 @@
 			 * @since 3.5.0
 			 * @since 4.6.0 The default now takes the original `memory_limit` into account.
 			 *
-			 * @param int|string $filtered_limit Maximum memory limit to allocate for images.
+			 * @param int|string $filtered_limit Maximum memory limit to allocate for image processing.
 			 *                                   Default `WP_MAX_MEMORY_LIMIT` or the original
 			 *                                   php.ini `memory_limit`, whichever is higher.
 			 *                                   Accepts an integer (bytes), or a shorthand string
@@ -7496,9 +7812,24 @@
 			$filtered_limit = apply_filters( 'image_memory_limit', $filtered_limit );
 			break;
 
+		case 'cron':
+			/**
+			 * Filters the memory limit allocated for WP-Cron event processing.
+			 *
+			 * @since 6.3.0
+			 *
+			 * @param int|string $filtered_limit Maximum memory limit to allocate for WP-Cron.
+			 *                                   Default `WP_MAX_MEMORY_LIMIT` or the original
+			 *                                   php.ini `memory_limit`, whichever is higher.
+			 *                                   Accepts an integer (bytes), or a shorthand string
+			 *                                   notation, such as '256M'.
+			 */
+			$filtered_limit = apply_filters( 'cron_memory_limit', $filtered_limit );
+			break;
+
 		default:
 			/**
-			 * Filters the memory limit allocated for arbitrary contexts.
+			 * Filters the memory limit allocated for an arbitrary context.
 			 *
 			 * The dynamic portion of the hook name, `$context`, refers to an arbitrary
 			 * context passed on calling the function. This allows for plugins to define
@@ -7506,8 +7837,8 @@
 			 *
 			 * @since 4.6.0
 			 *
-			 * @param int|string $filtered_limit Maximum memory limit to allocate for images.
-			 *                                   Default '256M' or the original php.ini `memory_limit`,
+			 * @param int|string $filtered_limit Maximum memory limit to allocate for this context.
+			 *                                   Default WP_MAX_MEMORY_LIMIT` or the original php.ini `memory_limit`,
 			 *                                   whichever is higher. Accepts an integer (bytes), or a
 			 *                                   shorthand string notation, such as '256M'.
 			 */
@@ -7535,7 +7866,7 @@
 }
 
 /**
- * Generate a random UUID (version 4).
+ * Generates a random UUID (version 4).
  *
  * @since 4.7.0
  *
@@ -7603,6 +7934,40 @@
 }
 
 /**
+ * Generates an incremental ID that is independent per each different prefix.
+ *
+ * It is similar to `wp_unique_id`, but each prefix has its own internal ID
+ * counter to make each prefix independent from each other. The ID starts at 1
+ * and increments on each call. The returned value is not universally unique,
+ * but it is unique across the life of the PHP process and it's stable per
+ * prefix.
+ *
+ * @since 6.4.0
+ *
+ * @param string $prefix Optional. Prefix for the returned ID. Default empty string.
+ * @return string Incremental ID per prefix.
+ */
+function wp_unique_prefixed_id( $prefix = '' ) {
+	static $id_counters = array();
+
+	if ( ! is_string( $prefix ) ) {
+		wp_trigger_error(
+			__FUNCTION__,
+			sprintf( 'The prefix must be a string. "%s" data type given.', gettype( $prefix ) )
+		);
+		$prefix = '';
+	}
+
+	if ( ! isset( $id_counters[ $prefix ] ) ) {
+		$id_counters[ $prefix ] = 0;
+	}
+
+	$id = ++$id_counters[ $prefix ];
+
+	return $prefix . (string) $id;
+}
+
+/**
  * Gets last changed date for the specified cache group.
  *
  * @since 4.7.0
@@ -7613,16 +7978,46 @@
 function wp_cache_get_last_changed( $group ) {
 	$last_changed = wp_cache_get( 'last_changed', $group );
 
-	if ( ! $last_changed ) {
-		$last_changed = microtime();
-		wp_cache_set( 'last_changed', $last_changed, $group );
-	}
-
-	return $last_changed;
-}
-
-/**
- * Send an email to the old site admin email address when the site admin email address changes.
+	if ( $last_changed ) {
+		return $last_changed;
+	}
+
+	return wp_cache_set_last_changed( $group );
+}
+
+/**
+ * Sets last changed date for the specified cache group to now.
+ *
+ * @since 6.3.0
+ *
+ * @param string $group Where the cache contents are grouped.
+ * @return string UNIX timestamp when the group was last changed.
+ */
+function wp_cache_set_last_changed( $group ) {
+	$previous_time = wp_cache_get( 'last_changed', $group );
+
+	$time = microtime();
+
+	wp_cache_set( 'last_changed', $time, $group );
+
+	/**
+	 * Fires after a cache group `last_changed` time is updated.
+	 * This may occur multiple times per page load and registered
+	 * actions must be performant.
+	 *
+	 * @since 6.3.0
+	 *
+	 * @param string    $group         The cache group name.
+	 * @param int       $time          The new last changed time.
+	 * @param int|false $previous_time The previous last changed time. False if not previously set.
+	 */
+	do_action( 'wp_cache_set_last_changed', $group, $time, $previous_time );
+
+	return $time;
+}
+
+/**
+ * Sends an email to the old site admin email address when the site admin email address changes.
  *
  * @since 4.9.0
  *
@@ -7719,7 +8114,7 @@
 }
 
 /**
- * Return an anonymized IPv4 or IPv6 address.
+ * Returns an anonymized IPv4 or IPv6 address.
  *
  * @since 4.9.6 Abstracted from `WP_Community_Events::get_unsafe_client_ip()`.
  *
@@ -7793,12 +8188,12 @@
 }
 
 /**
- * Return uniform "anonymous" data by type.
+ * Returns uniform "anonymous" data by type.
  *
  * @since 4.9.6
  *
  * @param string $type The type of data to be anonymized.
- * @param string $data Optional The data to be anonymized.
+ * @param string $data Optional. The data to be anonymized. Default empty string.
  * @return string The anonymous data for the requested type.
  */
 function wp_privacy_anonymize_data( $type, $data = '' ) {
@@ -7892,7 +8287,7 @@
 }
 
 /**
- * Schedule a `WP_Cron` job to delete expired export files.
+ * Schedules a `WP_Cron` job to delete expired export files.
  *
  * @since 4.9.6
  */
@@ -8010,15 +8405,23 @@
  *
  * @since 5.1.0
  * @since 5.2.0 Added the `$before` and `$after` parameters.
- *
- * @param string $before Markup to output before the annotation. Default `<p class="description">`.
- * @param string $after  Markup to output after the annotation. Default `</p>`.
- */
-function wp_update_php_annotation( $before = '<p class="description">', $after = '</p>' ) {
+ * @since 6.4.0 Added the `$display` parameter.
+ *
+ * @param string $before  Markup to output before the annotation. Default `<p class="description">`.
+ * @param string $after   Markup to output after the annotation. Default `</p>`.
+ * @param bool   $display Whether to echo or return the markup. Default `true` for echo.
+ *
+ * @return string|void
+ */
+function wp_update_php_annotation( $before = '<p class="description">', $after = '</p>', $display = true ) {
 	$annotation = wp_get_update_php_annotation();
 
 	if ( $annotation ) {
-		echo $before . $annotation . $after;
+		if ( $display ) {
+			echo $before . $annotation . $after;
+		} else {
+			return $before . $annotation . $after;
+		}
 	}
 }
 
@@ -8080,7 +8483,7 @@
 }
 
 /**
- * Display a button directly linking to a PHP update process.
+ * Displays a button directly linking to a PHP update process.
  *
  * This provides hosts with a way for users to be sent directly to their PHP update process.
  *
@@ -8097,10 +8500,10 @@
 
 	echo '<p class="button-container">';
 	printf(
-		'<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>',
+		'<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>',
 		esc_url( $direct_update_url ),
 		__( 'Update PHP' ),
-		/* translators: Accessibility text. */
+		/* translators: Hidden accessibility text. */
 		__( '(opens in a new tab)' )
 	);
 	echo '</p>';
@@ -8158,7 +8561,7 @@
  */
 function wp_get_default_update_https_url() {
 	/* translators: Documentation explaining HTTPS and why it should be used. */
-	return __( 'https://wordpress.org/support/article/why-should-i-use-https/' );
+	return __( 'https://developer.wordpress.org/advanced-administration/security/https/' );
 }
 
 /**
@@ -8192,7 +8595,7 @@
 }
 
 /**
- * Get the size of a directory.
+ * Gets the size of a directory.
  *
  * A helper function that is used primarily to check whether
  * a blog has exceeded its allowed upload space.
@@ -8207,8 +8610,10 @@
  */
 function get_dirsize( $directory, $max_execution_time = null ) {
 
-	// Exclude individual site directories from the total when checking the main site of a network,
-	// as they are subdirectories and should not be counted.
+	/*
+	 * Exclude individual site directories from the total when checking the main site of a network,
+	 * as they are subdirectories and should not be counted.
+	 */
 	if ( is_multisite() && is_main_site() ) {
 		$size = recurse_dirsize( $directory, $directory . '/sites', $max_execution_time );
 	} else {
@@ -8219,7 +8624,7 @@
 }
 
 /**
- * Get the size of a directory recursively.
+ * Gets the size of a directory recursively.
  *
  * Used by get_dirsize() to get a directory size when it contains other directories.
  *
@@ -8231,11 +8636,13 @@
  * @param string          $directory          Full path of a directory.
  * @param string|string[] $exclude            Optional. Full path of a subdirectory to exclude from the total,
  *                                            or array of paths. Expected without trailing slash(es).
+ *                                            Default null.
  * @param int             $max_execution_time Optional. Maximum time to run before giving up. In seconds.
  *                                            The timeout is global and is measured from the moment
- *                                            WordPress started to load.
+ *                                            WordPress started to load. Defaults to the value of
+ *                                            `max_execution_time` PHP setting.
  * @param array           $directory_cache    Optional. Array of cached directory paths.
- *
+ *                                            Defaults to the value of `dirsize_cache` transient.
  * @return int|false|null Size in bytes if a valid directory. False if not. Null if timeout.
  */
 function recurse_dirsize( $directory, $exclude = null, $max_execution_time = null, &$directory_cache = null ) {
@@ -8332,7 +8739,8 @@
 
 	// Only write the transient on the top level call and not on recursive calls.
 	if ( $save_cache ) {
-		set_transient( 'dirsize_cache', $directory_cache );
+		$expiration = ( wp_using_ext_object_cache() ) ? 0 : 10 * YEAR_IN_SECONDS;
+		set_transient( 'dirsize_cache', $directory_cache, $expiration );
 	}
 
 	return $size;
@@ -8350,7 +8758,8 @@
  */
 function clean_dirsize_cache( $path ) {
 	if ( ! is_string( $path ) || empty( $path ) ) {
-		trigger_error(
+		wp_trigger_error(
+			'',
 			sprintf(
 				/* translators: 1: Function name, 2: A variable type, like "boolean" or "integer". */
 				__( '%1$s only accepts a non-empty path string, received %2$s.' ),
@@ -8367,12 +8776,13 @@
 		return;
 	}
 
+	$expiration = ( wp_using_ext_object_cache() ) ? 0 : 10 * YEAR_IN_SECONDS;
 	if (
-		strpos( $path, '/' ) === false &&
-		strpos( $path, '\\' ) === false
+		! str_contains( $path, '/' ) &&
+		! str_contains( $path, '\\' )
 	) {
 		unset( $directory_cache[ $path ] );
-		set_transient( 'dirsize_cache', $directory_cache );
+		set_transient( 'dirsize_cache', $directory_cache, $expiration );
 		return;
 	}
 
@@ -8391,7 +8801,7 @@
 		unset( $directory_cache[ $path ] );
 	}
 
-	set_transient( 'dirsize_cache', $directory_cache );
+	set_transient( 'dirsize_cache', $directory_cache, $expiration );
 }
 
 /**
@@ -8410,6 +8820,14 @@
 	// Strip off any -alpha, -RC, -beta, -src suffixes.
 	list( $version ) = explode( '-', $wp_version );
 
+	if ( is_string( $required ) ) {
+		$trimmed = trim( $required );
+
+		if ( substr_count( $trimmed, '.' ) > 1 && str_ends_with( $trimmed, '.0' ) ) {
+			$required = substr( $trimmed, 0, -2 );
+		}
+	}
+
 	return empty( $required ) || version_compare( $version, $required, '>=' );
 }
 
@@ -8422,7 +8840,7 @@
  * @return bool True if required version is compatible or empty, false if not.
  */
 function is_php_version_compatible( $required ) {
-	return empty( $required ) || version_compare( phpversion(), $required, '>=' );
+	return empty( $required ) || version_compare( PHP_VERSION, $required, '>=' );
 }
 
 /**
@@ -8434,7 +8852,7 @@
  *
  * @param int|float $expected  The expected value.
  * @param int|float $actual    The actual number.
- * @param int|float $precision The allowed variation.
+ * @param int|float $precision Optional. The allowed variation. Default 1.
  * @return bool Whether the numbers match within the specified precision.
  */
 function wp_fuzzy_number_match( $expected, $actual, $precision = 1 ) {
@@ -8442,19 +8860,146 @@
 }
 
 /**
- * Sorts the keys of an array alphabetically.
- * The array is passed by reference so it doesn't get returned
- * which mimics the behaviour of ksort.
- *
- * @since 6.0.0
- *
- * @param array $array The array to sort, passed by reference.
- */
-function wp_recursive_ksort( &$array ) {
-	foreach ( $array as &$value ) {
-		if ( is_array( $value ) ) {
-			wp_recursive_ksort( $value );
-		}
-	}
-	ksort( $array );
-}
+ * Creates and returns the markup for an admin notice.
+ *
+ * @since 6.4.0
+ *
+ * @param string $message The message.
+ * @param array  $args {
+ *     Optional. An array of arguments for the admin notice. Default empty array.
+ *
+ *     @type string   $type               Optional. The type of admin notice.
+ *                                        For example, 'error', 'success', 'warning', 'info'.
+ *                                        Default empty string.
+ *     @type bool     $dismissible        Optional. Whether the admin notice is dismissible. Default false.
+ *     @type string   $id                 Optional. The value of the admin notice's ID attribute. Default empty string.
+ *     @type string[] $additional_classes Optional. A string array of class names. Default empty array.
+ *     @type string[] $attributes         Optional. Additional attributes for the notice div. Default empty array.
+ *     @type bool     $paragraph_wrap     Optional. Whether to wrap the message in paragraph tags. Default true.
+ * }
+ * @return string The markup for an admin notice.
+ */
+function wp_get_admin_notice( $message, $args = array() ) {
+	$defaults = array(
+		'type'               => '',
+		'dismissible'        => false,
+		'id'                 => '',
+		'additional_classes' => array(),
+		'attributes'         => array(),
+		'paragraph_wrap'     => true,
+	);
+
+	$args = wp_parse_args( $args, $defaults );
+
+	/**
+	 * Filters the arguments for an admin notice.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param array  $args    The arguments for the admin notice.
+	 * @param string $message The message for the admin notice.
+	 */
+	$args       = apply_filters( 'wp_admin_notice_args', $args, $message );
+	$id         = '';
+	$classes    = 'notice';
+	$attributes = '';
+
+	if ( is_string( $args['id'] ) ) {
+		$trimmed_id = trim( $args['id'] );
+
+		if ( '' !== $trimmed_id ) {
+			$id = 'id="' . $trimmed_id . '" ';
+		}
+	}
+
+	if ( is_string( $args['type'] ) ) {
+		$type = trim( $args['type'] );
+
+		if ( str_contains( $type, ' ' ) ) {
+			_doing_it_wrong(
+				__FUNCTION__,
+				sprintf(
+					/* translators: %s: The "type" key. */
+					__( 'The %s key must be a string without spaces.' ),
+					'<code>type</code>'
+				),
+				'6.4.0'
+			);
+		}
+
+		if ( '' !== $type ) {
+			$classes .= ' notice-' . $type;
+		}
+	}
+
+	if ( true === $args['dismissible'] ) {
+		$classes .= ' is-dismissible';
+	}
+
+	if ( is_array( $args['additional_classes'] ) && ! empty( $args['additional_classes'] ) ) {
+		$classes .= ' ' . implode( ' ', $args['additional_classes'] );
+	}
+
+	if ( is_array( $args['attributes'] ) && ! empty( $args['attributes'] ) ) {
+		$attributes = '';
+		foreach ( $args['attributes'] as $attr => $val ) {
+			if ( is_bool( $val ) ) {
+				$attributes .= $val ? ' ' . $attr : '';
+			} elseif ( is_int( $attr ) ) {
+				$attributes .= ' ' . esc_attr( trim( $val ) );
+			} elseif ( $val ) {
+				$attributes .= ' ' . $attr . '="' . esc_attr( trim( $val ) ) . '"';
+			}
+		}
+	}
+
+	if ( false !== $args['paragraph_wrap'] ) {
+		$message = "<p>$message</p>";
+	}
+
+	$markup = sprintf( '<div %1$sclass="%2$s"%3$s>%4$s</div>', $id, $classes, $attributes, $message );
+
+	/**
+	 * Filters the markup for an admin notice.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param string $markup  The HTML markup for the admin notice.
+	 * @param string $message The message for the admin notice.
+	 * @param array  $args    The arguments for the admin notice.
+	 */
+	return apply_filters( 'wp_admin_notice_markup', $markup, $message, $args );
+}
+
+/**
+ * Outputs an admin notice.
+ *
+ * @since 6.4.0
+ *
+ * @param string $message The message to output.
+ * @param array  $args {
+ *     Optional. An array of arguments for the admin notice. Default empty array.
+ *
+ *     @type string   $type               Optional. The type of admin notice.
+ *                                        For example, 'error', 'success', 'warning', 'info'.
+ *                                        Default empty string.
+ *     @type bool     $dismissible        Optional. Whether the admin notice is dismissible. Default false.
+ *     @type string   $id                 Optional. The value of the admin notice's ID attribute. Default empty string.
+ *     @type string[] $additional_classes Optional. A string array of class names. Default empty array.
+ *     @type string[] $attributes         Optional. Additional attributes for the notice div. Default empty array.
+ *     @type bool     $paragraph_wrap     Optional. Whether to wrap the message in paragraph tags. Default true.
+ * }
+ */
+function wp_admin_notice( $message, $args = array() ) {
+	/**
+	 * Fires before an admin notice is output.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @param string $message The message for the admin notice.
+	 * @param array  $args    The arguments for the admin notice.
+	 */
+	do_action( 'wp_admin_notice', $message, $args );
+
+	echo wp_kses_post( wp_get_admin_notice( $message, $args ) );
+}