wp_version_check()
云策文档标注
概述
wp_version_check() 是 WordPress 核心函数,用于检查当前 WordPress 版本与最新版本之间的差异。它通过向 api.wordpress.org 发送请求,收集系统信息(如 PHP 版本、MySQL 版本、扩展等)并返回更新数据,仅在非安装模式下执行。
关键要点
- 函数用于检查 WordPress 核心更新,发送数据到 api.wordpress.org,包括版本、PHP、MySQL、扩展等信息。
- 接受两个可选参数:$extra_stats(额外统计数组)和 $force_check(强制检查布尔值),若 $extra_stats 非空则自动强制检查。
- 使用 transient 缓存(update_core)优化性能,默认每分钟检查一次,避免频繁请求。
- 包含多个过滤器(如 core_version_check_locale 和 core_version_check_query_args)允许开发者自定义检查行为。
- 处理多站点环境、图像支持(GD/Imagick)和数据库引擎(MyISAM)等细节,确保数据准确性。
- 错误处理机制:支持 SSL 回退,并在失败时记录警告信息。
代码示例
function wp_version_check( $extra_stats = array(), $force_check = false ) {
global $wpdb, $wp_local_package;
if ( wp_installing() ) {
return;
}
// 基本版本检查逻辑
$current = get_site_transient( 'update_core' );
if ( ! is_object( $current ) ) {
$current = new stdClass();
$current->updates = array();
$current->version_checked = wp_get_wp_version();
}
if ( ! empty( $extra_stats ) ) {
$force_check = true;
}
// 强制检查或超时逻辑
$timeout = MINUTE_IN_SECONDS;
$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
if ( ! $force_check && $time_not_changed ) {
return;
}
// 构建查询数据并发送请求
$query = array(
'version' => wp_get_wp_version(),
'php' => PHP_VERSION,
// 更多字段...
);
$url = 'https://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, '', '&' );
$response = wp_remote_post( $url, $options );
// 处理响应并更新 transient
if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( is_array( $body ) && isset( $body['offers'] ) ) {
$updates = new stdClass();
$updates->updates = $body['offers'];
set_site_transient( 'update_core', $updates );
}
}
}注意事项
- 修改 core_version_check_query_args 过滤器可能影响安全更新接收,需谨慎操作。
- 函数在 WordPress 安装过程中(wp_installing() 返回 true)不会执行。
- 依赖多个 WordPress 核心函数和类(如 wpdb、transient 相关函数),确保环境兼容。
原文内容
Checks WordPress version against the newest version.
Description
The WordPress version, PHP version, and locale is sent to api.wordpress.org.
Checks against the WordPress server at api.wordpress.org. Will only check if WordPress isn’t installing.
Parameters
$extra_statsarrayoptional-
Extra statistics to report to the WordPress.org API.
Default:
array() $force_checkbooloptional-
Whether to bypass the transient cache and force a fresh update check.
Defaults to false, true if $extra_stats is set.Default:
false
Source
function wp_version_check( $extra_stats = array(), $force_check = false ) {
global $wpdb, $wp_local_package;
if ( wp_installing() ) {
return;
}
$php_version = PHP_VERSION;
$current = get_site_transient( 'update_core' );
$translations = wp_get_installed_translations( 'core' );
// Invalidate the transient when $wp_version changes.
if ( is_object( $current ) && wp_get_wp_version() !== $current->version_checked ) {
$current = false;
}
if ( ! is_object( $current ) ) {
$current = new stdClass();
$current->updates = array();
$current->version_checked = wp_get_wp_version();
}
if ( ! empty( $extra_stats ) ) {
$force_check = true;
}
// Wait 1 minute between multiple version check requests.
$timeout = MINUTE_IN_SECONDS;
$time_not_changed = isset( $current->last_checked ) && $timeout > ( time() - $current->last_checked );
if ( ! $force_check && $time_not_changed ) {
return;
}
/**
* Filters the locale requested for WordPress core translations.
*
* @since 2.8.0
*
* @param string $locale Current locale.
*/
$locale = apply_filters( 'core_version_check_locale', get_locale() );
// Update last_checked for current to prevent multiple blocking requests if request hangs.
$current->last_checked = time();
set_site_transient( 'update_core', $current );
if ( method_exists( $wpdb, 'db_server_info' ) ) {
$mysql_version = $wpdb->db_server_info();
} elseif ( method_exists( $wpdb, 'db_version' ) ) {
$mysql_version = preg_replace( '/[^0-9.].*/', '', $wpdb->db_version() );
} else {
$mysql_version = 'N/A';
}
if ( is_multisite() ) {
$num_blogs = get_blog_count();
$wp_install = network_site_url();
$multisite_enabled = 1;
} else {
$multisite_enabled = 0;
$num_blogs = 1;
$wp_install = home_url( '/' );
}
$extensions = get_loaded_extensions();
sort( $extensions, SORT_STRING | SORT_FLAG_CASE );
$query = array(
'version' => wp_get_wp_version(),
'php' => $php_version,
'locale' => $locale,
'mysql' => $mysql_version,
'local_package' => isset( $wp_local_package ) ? $wp_local_package : '',
'blogs' => $num_blogs,
'users' => get_user_count(),
'multisite_enabled' => $multisite_enabled,
'initial_db_version' => get_site_option( 'initial_db_version' ),
'myisam_tables' => array(),
'extensions' => array_combine( $extensions, array_map( 'phpversion', $extensions ) ),
'platform_flags' => array(
'os' => PHP_OS,
'bits' => PHP_INT_SIZE === 4 ? 32 : 64,
),
'image_support' => array(),
);
// Check for default tables using the MyISAM engine.
$table_names = implode( "','", $wpdb->tables() );
$myisam_tables = $wpdb->get_results(
$wpdb->prepare(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- This query cannot use interpolation.
"SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME IN ('$table_names') AND ENGINE = %s;",
DB_NAME,
'MyISAM'
),
OBJECT_K
);
if ( ! empty( $myisam_tables ) ) {
$all_unprefixed_tables = $wpdb->tables( 'all', false );
// Including the table prefix is not necessary.
$unprefixed_myisam_tables = array_reduce(
array_keys( $myisam_tables ),
function ( $carry, $prefixed_myisam_table ) use ( $all_unprefixed_tables ) {
foreach ( $all_unprefixed_tables as $unprefixed ) {
if ( str_ends_with( $prefixed_myisam_table, $unprefixed ) ) {
$carry[] = $unprefixed;
break;
}
}
return $carry;
},
array()
);
$query['myisam_tables'] = $unprefixed_myisam_tables;
}
if ( function_exists( 'gd_info' ) ) {
$gd_info = gd_info();
// Filter to supported values.
$gd_info = array_filter( $gd_info );
// Add data for GD WebP, AVIF, HEIC and JPEG XL support.
$query['image_support']['gd'] = array_keys(
array_filter(
array(
'webp' => isset( $gd_info['WebP Support'] ),
'avif' => isset( $gd_info['AVIF Support'] ),
'heic' => isset( $gd_info['HEIC Support'] ),
'jxl' => isset( $gd_info['JXL Support'] ),
)
)
);
}
if ( class_exists( 'Imagick' ) ) {
// Add data for Imagick WebP, AVIF, HEIC and JPEG XL support.
$query['image_support']['imagick'] = array_keys(
array_filter(
array(
'webp' => ! empty( Imagick::queryFormats( 'WEBP' ) ),
'avif' => ! empty( Imagick::queryFormats( 'AVIF' ) ),
'heic' => ! empty( Imagick::queryFormats( 'HEIC' ) ),
'jxl' => ! empty( Imagick::queryFormats( 'JXL' ) ),
)
)
);
}
/**
* Filters the query arguments sent as part of the core version check.
*
* WARNING: Changing this data may result in your site not receiving security updates.
* Please exercise extreme caution.
*
* @since 4.9.0
* @since 6.1.0 Added `$extensions`, `$platform_flags`, and `$image_support` to the `$query` parameter.
*
* @param array $query {
* Version check query arguments.
*
* @type string $version WordPress version number.
* @type string $php PHP version number.
* @type string $locale The locale to retrieve updates for.
* @type string $mysql MySQL version number.
* @type string $local_package The value of the $wp_local_package global, when set.
* @type int $blogs Number of sites on this WordPress installation.
* @type int $users Number of users on this WordPress installation.
* @type int $multisite_enabled Whether this WordPress installation uses Multisite.
* @type int $initial_db_version Database version of WordPress at time of installation.
* @type array $extensions List of PHP extensions and their versions.
* @type array $platform_flags List containing the operating system name and bit support.
* @type array $image_support List of image formats supported by GD and Imagick.
* }
*/
$query = apply_filters( 'core_version_check_query_args', $query );
$post_body = array(
'translations' => wp_json_encode( $translations ),
);
if ( is_array( $extra_stats ) ) {
$post_body = array_merge( $post_body, $extra_stats );
}
// Allow for WP_AUTO_UPDATE_CORE to specify beta/RC/development releases.
if ( defined( 'WP_AUTO_UPDATE_CORE' )
&& in_array( WP_AUTO_UPDATE_CORE, array( 'beta', 'rc', 'development', 'branch-development' ), true )
) {
$query['channel'] = WP_AUTO_UPDATE_CORE;
}
$url = 'https://api.wordpress.org/core/version-check/1.7/?' . http_build_query( $query, '', '&' );
$http_url = $url;
$ssl = wp_http_supports( array( 'ssl' ) );
if ( $ssl ) {
$url = set_url_scheme( $url, 'https' );
}
$doing_cron = wp_doing_cron();
$options = array(
'timeout' => $doing_cron ? 30 : 3,
'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
'headers' => array(
'wp_install' => $wp_install,
'wp_blog' => home_url( '/' ),
),
'body' => $post_body,
);
$response = wp_remote_post( $url, $options );
if ( $ssl && is_wp_error( $response ) ) {
wp_trigger_error(
__FUNCTION__,
sprintf(
/* translators: %s: Support forums URL. */
__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
__( 'https://wordpress.org/support/forums/' )
) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
);
$response = wp_remote_post( $http_url, $options );
}
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
return;
}
$body = trim( wp_remote_retrieve_body( $response ) );
$body = json_decode( $body, true );
if ( ! is_array( $body ) || ! isset( $body['offers'] ) ) {
return;
}
$offers = $body['offers'];
foreach ( $offers as &$offer ) {
foreach ( $offer as $offer_key => $value ) {
if ( 'packages' === $offer_key ) {
$offer['packages'] = (object) array_intersect_key(
array_map( 'esc_url', $offer['packages'] ),
array_fill_keys( array( 'full', 'no_content', 'new_bundled', 'partial', 'rollback' ), '' )
);
} elseif ( 'download' === $offer_key ) {
$offer['download'] = esc_url( $value );
} else {
$offer[ $offer_key ] = esc_html( $value );
}
}
$offer = (object) array_intersect_key(
$offer,
array_fill_keys(
array(
'response',
'download',
'locale',
'packages',
'current',
'version',
'php_version',
'mysql_version',
'new_bundled',
'partial_version',
'notify_email',
'support_email',
'new_files',
),
''
)
);
}
$updates = new stdClass();
$updates->updates = $offers;
$updates->last_checked = time();
$updates->version_checked = wp_get_wp_version();
if ( isset( $body['translations'] ) ) {
$updates->translations = $body['translations'];
}
set_site_transient( 'update_core', $updates );
if ( ! empty( $body['ttl'] ) ) {
$ttl = (int) $body['ttl'];
if ( $ttl && ( time() + $ttl < wp_next_scheduled( 'wp_version_check' ) ) ) {
// Queue an event to re-run the update check in $ttl seconds.
wp_schedule_single_event( time() + $ttl, 'wp_version_check' );
}
}
// Trigger background updates if running non-interactively, and we weren't called from the update handler.
if ( $doing_cron && ! doing_action( 'wp_maybe_auto_update' ) ) {
/**
* Fires during wp_cron, starting the auto-update process.
*
* @since 3.9.0
*/
do_action( 'wp_maybe_auto_update' );
}
}
Hooks
- apply_filters( ‘core_version_check_locale’, string $locale )
-
Filters the locale requested for WordPress core translations.
- apply_filters( ‘core_version_check_query_args’, array $query )
-
Filters the query arguments sent as part of the core version check.
- do_action( ‘wp_maybe_auto_update’ )
-
Fires during wp_cron, starting the auto-update process.
Changelog
| Version | Description |
|---|---|
| 2.3.0 | Introduced. |