ksort( $_wp_admin_css_colors );
if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
// Set Default ('fresh') and Light should go first.
$_wp_admin_css_colors = array_filter(
$current_color = get_user_option( 'admin_color', $user_id );
if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
$current_color = 'fresh';
<fieldset id="color-picker" class="scheme-list">
<legend class="screen-reader-text"><span>
/* translators: Hidden accessibility text. */
_e( 'Admin Color Scheme' );
wp_nonce_field( 'save-color-scheme', 'color-nonce', false );
foreach ( $_wp_admin_css_colors as $color => $color_info ) :
<div class="color-option <?php echo ( $color === $current_color ) ? 'selected' : ''; ?>">
<input name="admin_color" id="admin_color_<?php echo esc_attr( $color ); ?>" type="radio" value="<?php echo esc_attr( $color ); ?>" class="tog" <?php checked( $color, $current_color ); ?> />
<input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" />
<input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
<label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label>
<div class="color-palette">
foreach ( $color_info->colors as $html_color ) {
<div class="color-palette-shade" style="background-color: <?php echo esc_attr( $html_color ); ?>"> </div>
* @global array $_wp_admin_css_colors
function wp_color_scheme_settings() {
global $_wp_admin_css_colors;
$color_scheme = get_user_option( 'admin_color' );
// It's possible to have a color scheme set that is no longer registered.
if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) {
if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) {
$icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
} elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
$icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
// Fall back to the default set of icon colors if the default scheme is missing.
echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
* Displays the viewport meta in the admin.
function wp_admin_viewport_meta() {
* Filters the viewport meta in the admin.
* @param string $viewport_meta The viewport meta.
$viewport_meta = apply_filters( 'admin_viewport_meta', 'width=device-width,initial-scale=1.0' );
if ( empty( $viewport_meta ) ) {
echo '<meta name="viewport" content="' . esc_attr( $viewport_meta ) . '">';
* Adds viewport meta for mobile in Customizer.
* Hooked to the {@see 'admin_viewport_meta'} filter.
* @param string $viewport_meta The viewport meta.
* @return string Filtered viewport meta.
function _customizer_mobile_viewport_meta( $viewport_meta ) {
return trim( $viewport_meta, ',' ) . ',minimum-scale=0.5,maximum-scale=1.2';
* Checks lock status for posts displayed on the Posts screen.
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @param string $screen_id The screen ID.
* @return array The Heartbeat response.
function wp_check_locked_posts( $response, $data, $screen_id ) {
if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
foreach ( $data['wp-check-locked-posts'] as $key ) {
$post_id = absint( substr( $key, 5 ) );
$user_id = wp_check_post_lock( $post_id );
$user = get_userdata( $user_id );
if ( $user && current_user_can( 'edit_post', $post_id ) ) {
'name' => $user->display_name,
/* translators: %s: User's display name. */
'text' => sprintf( __( '%s is currently editing' ), $user->display_name ),
if ( get_option( 'show_avatars' ) ) {
$send['avatar_src'] = get_avatar_url( $user->ID, array( 'size' => 18 ) );
$send['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 36 ) );
$checked[ $key ] = $send;
if ( ! empty( $checked ) ) {
$response['wp-check-locked-posts'] = $checked;
* Checks lock status on the New/Edit Post screen and refresh the lock.
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @param string $screen_id The screen ID.
* @return array The Heartbeat response.
function wp_refresh_post_lock( $response, $data, $screen_id ) {
if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
$received = $data['wp-refresh-post-lock'];
$post_id = absint( $received['post_id'] );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
$user_id = wp_check_post_lock( $post_id );
$user = get_userdata( $user_id );
'name' => $user->display_name,
/* translators: %s: User's display name. */
'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ),
if ( get_option( 'show_avatars' ) ) {
$error['avatar_src'] = get_avatar_url( $user->ID, array( 'size' => 64 ) );
$error['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 128 ) );
$send['lock_error'] = $error;
$new_lock = wp_set_post_lock( $post_id );
$send['new_lock'] = implode( ':', $new_lock );
$response['wp-refresh-post-lock'] = $send;
* Checks nonce expiration on the New/Edit Post screen and refresh if needed.
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @param string $screen_id The screen ID.
* @return array The Heartbeat response.
function wp_refresh_post_nonces( $response, $data, $screen_id ) {
if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
$received = $data['wp-refresh-post-nonces'];
$response['wp-refresh-post-nonces'] = array( 'check' => 1 );
$post_id = absint( $received['post_id'] );
if ( ! current_user_can( 'edit_post', $post_id ) ) {
$response['wp-refresh-post-nonces'] = array(
'getpermalinknonce' => wp_create_nonce( 'getpermalink' ),
'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ),
'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ),
'_ajax_linking_nonce' => wp_create_nonce( 'internal-linking' ),
'_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
* Refresh nonces used with meta boxes in the block editor.
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @return array The Heartbeat response.
function wp_refresh_metabox_loader_nonces( $response, $data ) {
if ( empty( $data['wp-refresh-metabox-loader-nonces'] ) ) {
$received = $data['wp-refresh-metabox-loader-nonces'];
$post_id = (int) $received['post_id'];
if ( ! current_user_can( 'edit_post', $post_id ) ) {
$response['wp-refresh-metabox-loader-nonces'] = array(
'metabox_loader_nonce' => wp_create_nonce( 'meta-box-loader' ),
'_wpnonce' => wp_create_nonce( 'update-post_' . $post_id ),
* Adds the latest Heartbeat and REST API nonce to the Heartbeat response.
* @param array $response The Heartbeat response.
* @return array The Heartbeat response.
function wp_refresh_heartbeat_nonces( $response ) {
// Refresh the Rest API nonce.
$response['rest_nonce'] = wp_create_nonce( 'wp_rest' );
// Refresh the Heartbeat nonce.
$response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' );
* Disables suspension of Heartbeat on the Add/Edit Post screens.
* @global string $pagenow The filename of the current screen.
* @param array $settings An array of Heartbeat settings.
* @return array Filtered Heartbeat settings.
function wp_heartbeat_set_suspension( $settings ) {
if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
$settings['suspension'] = 'disable';
* Performs autosave with heartbeat.
* @param array $response The Heartbeat response.
* @param array $data The $_POST data sent.
* @return array The Heartbeat response.
function heartbeat_autosave( $response, $data ) {
if ( ! empty( $data['wp_autosave'] ) ) {
$saved = wp_autosave( $data['wp_autosave'] );
if ( is_wp_error( $saved ) ) {
$response['wp_autosave'] = array(
'message' => $saved->get_error_message(),
} elseif ( empty( $saved ) ) {
$response['wp_autosave'] = array(
'message' => __( 'Error while saving.' ),
/* translators: Draft saved date format, see https://www.php.net/manual/datetime.format.php */
$draft_saved_date_format = __( 'g:i:s a' );
$response['wp_autosave'] = array(
/* translators: %s: Date and time. */
'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ),
* Removes single-use URL parameters and create canonical link based on new URL.
* Removes specific query string parameters from a URL, create the canonical link,
* put it in the admin header, and change the current URL to match.
function wp_admin_canonical_url() {
$removable_query_args = wp_removable_query_args();
if ( empty( $removable_query_args ) ) {
// Ensure we're using an absolute URL.
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
$filtered_url = remove_query_arg( $removable_query_args, $current_url );
* Filters the admin canonical URL value.
* @param string $filtered_url The admin canonical URL value.
$filtered_url = apply_filters( 'wp_admin_canonical_url', $filtered_url );
<link id="wp-admin-canonical" rel="canonical" href="<?php echo esc_url( $filtered_url ); ?>" />
if ( window.history.replaceState ) {
window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );
* Outputs JS that reloads the page if the user navigated to it with the Back or Forward button.
* Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache,
* so the post title and editor content are the last saved versions. Ideally this script should run first in the head.
function wp_page_reload_on_back_button_js() {
if ( typeof performance !== 'undefined' && performance.navigation && performance.navigation.type === 2 ) {
document.location.reload( true );
* Sends a confirmation request email when a change of site admin email address is attempted.
* The new site admin address will not become active until confirmed.
* @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific.
* @param string $old_value The old site admin email address.
* @param string $value The proposed new site admin email address.
function update_option_new_admin_email( $old_value, $value ) {
if ( get_option( 'admin_email' ) === $value || ! is_email( $value ) ) {
$hash = md5( $value . time() . wp_rand() );
$new_admin_email = array(
update_option( 'adminhash', $new_admin_email, false );
$switched_locale = switch_to_user_locale( get_current_user_id() );
/* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
A site administrator (###USERNAME###) recently requested to have the
administration email address changed on this site:
To confirm this change, please click on the following link:
You can safely ignore and delete this email if you do not want to
This email has been sent to ###EMAIL###
* Filters the text of the email sent when a change of site admin email address is attempted.
* The following strings have a special meaning and will get replaced dynamically:
* - ###USERNAME### The current user's username.
* - ###ADMIN_URL### The link to click on to confirm the email change.
* - ###EMAIL### The proposed new site admin email address.
* - ###SITENAME### The name of the site.
* - ###SITEURL### The URL to the site.
* @since 4.9.0 This filter is no longer Multisite specific.
* @param string $email_text Text in the email.
* @param array $new_admin_email {
* Data relating to the new site admin email address.
* @type string $hash The secure hash used in the confirmation link URL.
* @type string $newemail The proposed new site admin email address.