大家好,我是你们今天的WordPress更新函数源码剖析讲师,咱们今天不讲虚的,直接上干货,带大家一起扒一扒WordPress的wp_update_plugins()
和wp_update_themes()
这两个“更新小能手”的底裤。
开场白:更新的艺术,远不止点个按钮那么简单
咱们平时用WordPress,点一下“更新”按钮,插件或者主题就乖乖升级了,感觉一切都很简单。但你知道背后发生了什么吗?wp_update_plugins()
和wp_update_themes()
这两个函数就是幕后英雄,它们负责检查更新、下载新版本、解压安装,然后默默地守护着你的网站安全。
第一部分: wp_update_plugins()
– 插件更新的秘密
wp_update_plugins()
函数位于/wp-admin/includes/update.php
文件中,它的主要职责是更新插件。
1. 初始准备:检查权限和环境
首先,函数会检查当前用户是否有权限更新插件。毕竟,不能让随便什么人都能“动手动脚”嘛。
function wp_update_plugins() {
include_once ABSPATH . 'wp-admin/includes/plugin.php'; // 加载插件管理函数
include_once ABSPATH . 'wp-admin/includes/update.php'; // 确保更新函数可用
if ( ! current_user_can( 'update_plugins' ) ) {
wp_die(
sprintf(
'<h1>%1$s</h1><p>%2$s</p>',
__( 'Cheatin’ uh?' ),
__( 'You do not have sufficient permissions to update plugins for this site.' )
),
403
);
}
// 检查是否禁用文件编辑
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
wp_die( __( 'File modifications are disabled.' ) );
}
// 检查是否安装了WordPress文件系统抽象层 (Filesystem API)
$wp_filesystem = WP_Filesystem(); // 初始化文件系统
if ( ! $wp_filesystem ) {
return false; // 如果初始化失败,则返回false
}
// ... 更多代码
}
这段代码做了几件事:
- 加载依赖文件: 确保
plugin.php
和update.php
中的函数可用。 - 权限检查:
current_user_can( 'update_plugins' )
检查当前用户是否拥有update_plugins
权限。如果没权限,直接报错,不给更新。 - 禁用文件修改检查:
DISALLOW_FILE_MODS
常量如果被定义为true
,说明网站管理员禁止了文件修改,这时候也无法更新。 - 文件系统API检查:
WP_Filesystem()
函数初始化WordPress的文件系统API。如果初始化失败(比如权限问题),更新也会失败。
2. 获取插件更新信息:从哪里知道有更新?
接下来,wp_update_plugins()
会获取插件的更新信息。这个信息通常来自WordPress.org官方插件仓库,或者你自己搭建的私有仓库(如果你有的话)。
$current = get_site_transient( 'update_plugins' );
if ( ! isset( $current->response ) || ! is_array( $current->response ) ) {
$current->response = array();
}
$plugins = isset( $_POST['plugins'] ) ? (array) $_POST['plugins'] : array();
// ... 更多代码
这里:
get_site_transient( 'update_plugins' )
从数据库中获取缓存的插件更新信息。这个信息包含了哪些插件需要更新,以及新版本的下载地址等。$_POST['plugins']
: 客户端(通常是WordPress后台)通过POST请求传递要更新的插件列表。
3. 开始更新循环:一个一个来,排队升级
现在,有了需要更新的插件列表,就可以开始逐个更新了。
$errors = array();
$results = array();
set_time_limit( 300 ); // 增加执行时间限制
foreach ( $plugins as $plugin ) {
$result = wp_update_plugin( $plugin ); // 调用wp_update_plugin函数更新单个插件
if ( is_wp_error( $result ) ) {
$errors[ $plugin ] = $result;
} else {
$results[ $plugin ] = true;
}
}
// ... 更多代码
- 循环更新:
foreach
循环遍历需要更新的插件。 - 单个插件更新:
wp_update_plugin( $plugin )
函数负责更新单个插件。这个函数才是真正的“干活的”。 - 错误处理: 如果更新过程中出现错误,
is_wp_error( $result )
会检测到,并将错误信息记录下来。
4. wp_update_plugin()
:单个插件更新的流程
wp_update_plugin()
函数是更新单个插件的核心。
function wp_update_plugin( $plugin ) {
include_once ABSPATH . 'wp-admin/includes/file.php'; // 文件操作函数
include_once ABSPATH . 'wp-admin/includes/plugin.php'; // 插件管理函数
$current = get_site_transient( 'update_plugins' );
if ( ! isset( $current->response[ $plugin ] ) ) {
return new WP_Error( 'no_update', __( 'No update available.' ) );
}
$r = $current->response[ $plugin ];
$skin = new Automatic_Upgrader_Skin(); // 使用自动升级皮肤
$upgrader = new Plugin_Upgrader( $skin ); // 创建插件升级器对象
$result = $upgrader->upgrade( $plugin, array(
'clear_update_cache' => false, // 不清除更新缓存,因为可能还有其他插件需要更新
) );
if ( is_wp_error( $result ) ) {
return $result;
} elseif ( $result ) {
// 插件更新成功后,清除插件缓存
clean_plugins_cache();
}
return true;
}
- 检查更新信息: 确保该插件确实有更新可用。
- 创建升级器:
Plugin_Upgrader
类负责处理插件的下载、解压、安装等操作。 - 开始升级:
$upgrader->upgrade( $plugin )
执行升级操作。 - 清理缓存:
clean_plugins_cache()
清除插件缓存,确保WordPress能正确识别新版本。
5. Plugin_Upgrader::upgrade()
:升级的细节
Plugin_Upgrader::upgrade()
函数是插件升级的关键。它会:
- 备份插件: (如果需要)在升级前备份旧版本的插件,以防万一。
- 下载新版本: 从更新服务器下载新版本的插件压缩包。
- 解压插件: 将压缩包解压到临时目录。
- 停用插件: 停用旧版本的插件。
- 删除旧版本: 删除旧版本的插件目录。
- 移动新版本: 将解压后的新版本插件移动到插件目录。
- 启用插件: 重新启用插件。
- 清理临时文件: 删除临时文件。
这个过程涉及到很多文件操作,如果权限不足或者文件系统出现问题,升级就会失败。
第二部分: wp_update_themes()
– 主题更新的艺术
wp_update_themes()
函数位于/wp-admin/includes/update.php
文件中,它的作用和wp_update_plugins()
类似,只不过是负责更新主题。
1. 初始准备:检查权限和环境
和更新插件一样,更新主题也需要权限。
function wp_update_themes() {
include_once ABSPATH . 'wp-admin/includes/theme.php'; // 加载主题管理函数
include_once ABSPATH . 'wp-admin/includes/update.php'; // 确保更新函数可用
if ( ! current_user_can( 'update_themes' ) ) {
wp_die(
sprintf(
'<h1>%1$s</h1><p>%2$s</p>',
__( 'Cheatin’ uh?' ),
__( 'You do not have sufficient permissions to update themes for this site.' )
),
403
);
}
// 检查是否禁用文件编辑
if ( defined( 'DISALLOW_FILE_MODS' ) && DISALLOW_FILE_MODS ) {
wp_die( __( 'File modifications are disabled.' ) );
}
// 检查是否安装了WordPress文件系统抽象层 (Filesystem API)
$wp_filesystem = WP_Filesystem();
if ( ! $wp_filesystem ) {
return false;
}
// ... 更多代码
}
这段代码和wp_update_plugins()
的初始准备几乎一样,只是权限检查变成了current_user_can( 'update_themes' )
。
2. 获取主题更新信息
wp_update_themes()
会从数据库中获取缓存的主题更新信息。
$current = get_site_transient( 'update_themes' );
if ( ! isset( $current->response ) || ! is_array( $current->response ) ) {
$current->response = array();
}
$themes = isset( $_POST['themes'] ) ? (array) $_POST['themes'] : array();
// ... 更多代码
get_site_transient( 'update_themes' )
:获取缓存的主题更新信息。$_POST['themes']
:客户端传递要更新的主题列表。
3. 开始更新循环
$errors = array();
$results = array();
set_time_limit( 300 );
foreach ( $themes as $theme ) {
$result = wp_update_theme( $theme ); // 调用wp_update_theme更新单个主题
if ( is_wp_error( $result ) ) {
$errors[ $theme ] = $result;
} else {
$results[ $theme ] = true;
}
}
// ... 更多代码
- 循环更新: 遍历要更新的主题。
- 单个主题更新:
wp_update_theme( $theme )
负责更新单个主题。 - 错误处理: 记录更新过程中出现的错误。
4. wp_update_theme()
:单个主题更新的流程
function wp_update_theme( $theme ) {
include_once ABSPATH . 'wp-admin/includes/file.php'; // 文件操作函数
include_once ABSPATH . 'wp-admin/includes/theme.php'; // 主题管理函数
$current = get_site_transient( 'update_themes' );
if ( ! isset( $current->response[ $theme ] ) ) {
return new WP_Error( 'no_update', __( 'No update available.' ) );
}
$r = $current->response[ $theme ];
$skin = new Automatic_Upgrader_Skin(); // 使用自动升级皮肤
$upgrader = new Theme_Upgrader( $skin ); // 创建主题升级器对象
$result = $upgrader->upgrade( $theme, array(
'clear_update_cache' => false, // 不清除缓存,因为可能还有其他主题需要更新
) );
if ( is_wp_error( $result ) ) {
return $result;
} elseif ( $result ) {
// 主题更新成功后,清除主题缓存
clean_theme_cache();
}
return true;
}
- 检查更新信息: 确保该主题确实有更新可用。
- 创建升级器:
Theme_Upgrader
类负责处理主题的下载、解压、安装等操作。 - 开始升级:
$upgrader->upgrade( $theme )
执行升级操作。 - 清理缓存:
clean_theme_cache()
清除主题缓存。
5. Theme_Upgrader::upgrade()
:升级的细节
Theme_Upgrader::upgrade()
函数的流程和Plugin_Upgrader::upgrade()
非常相似:
- 备份主题: (如果需要)备份旧版本的主题。
- 下载新版本: 从更新服务器下载新版本的主题压缩包。
- 解压主题: 将压缩包解压到临时目录。
- 删除旧版本: 删除旧版本的主题目录。
- 移动新版本: 将解压后的新版本主题移动到主题目录。
- 清理临时文件: 删除临时文件。
第三部分:一些关键的类和函数
咱们来总结一下,在插件和主题更新过程中,几个关键的类和函数:
类/函数 | 作用 |
---|---|
WP_Filesystem() |
WordPress文件系统API,用于文件操作,例如读取、写入、删除文件。 |
get_site_transient() |
从数据库中获取瞬态数据(transient),瞬态数据是临时存储的数据,用于缓存更新信息等。 |
Plugin_Upgrader |
插件升级器类,负责处理插件的下载、解压、安装等操作。 |
Theme_Upgrader |
主题升级器类,负责处理主题的下载、解压、安装等操作。 |
Automatic_Upgrader_Skin |
自动升级皮肤类,用于在后台显示升级过程的信息,例如下载进度、解压进度等。 |
wp_update_plugin() |
更新单个插件的函数。 |
wp_update_theme() |
更新单个主题的函数。 |
clean_plugins_cache() |
清除插件缓存,确保WordPress能正确识别新版本。 |
clean_theme_cache() |
清除主题缓存,确保WordPress能正确识别新版本。 |
第四部分:常见问题和注意事项
- 权限问题: 更新插件和主题需要服务器有足够的权限。如果权限不足,可能会导致更新失败。
- 文件系统问题: 如果服务器的文件系统出现问题,例如磁盘空间不足、文件损坏等,也可能导致更新失败。
- 兼容性问题: 新版本的插件或主题可能与你的WordPress版本或其他插件不兼容。在更新之前,最好先备份网站,以防万一。
- 缓存问题: 有时候,即使插件或主题已经更新成功,WordPress仍然显示旧版本。这时候,可以尝试清除缓存。
- 网络问题: 下载新版本的插件或主题需要连接到更新服务器。如果网络连接不稳定,可能会导致下载失败。
- 更新失败后的处理: 如果更新失败,不要慌张。首先查看错误日志,找到错误原因。然后,可以尝试手动更新,或者恢复备份。
总结:更新虽易,理解不易,且行且珍惜
wp_update_plugins()
和wp_update_themes()
这两个函数,看似简单,背后却隐藏着复杂的逻辑。理解它们的源码,可以帮助我们更好地理解WordPress的更新机制,解决更新过程中遇到的问题,甚至可以自定义更新流程。
希望今天的讲解对大家有所帮助。记住,更新有风险,操作需谨慎!在更新之前,一定要备份网站!备份!备份!重要的事情说三遍。
今天就到这里,下课!