[WordPress源码分析]插件配置更新

WordPress有一套注册和修改配置的机制,很多插件设置都基于这套机制实现。以BAE-Helper为例,插件的配置都是通过wp-admin/options.php更新的,详见《[BAE-Helper]实现分析v0.1》。而具体WordPress是怎么更新配置的,则需要通过源码来了解。

1. 配置更新表单

插件要通过wp-admin/options.php更新配置,需要构造相应的表单请求,WordPress为此提供了辅助函数settings_fields($option_group)。函数以插件对应的配置组为参数,用于给插件生成必要的请求参数,内容如下。

<input value="bae-helper-settings-group" name="option_page" type="hidden">
<input value="update" name="action" type="hidden">
<input value="40099a7e66" name="_wpnonce" id="_wpnonce" type="hidden">
<input value="/wp-admin/options-general.php?page=bae_helper_settings&amp;settings-updated=true" 
		name="_wp_http_referer" type="hidden">

其中,“option_page”指明对应更新的是哪一个配置组;“action”表明请求是用于更新配置的;“_wpnonce”是WordPress中类似CSRF Token的东西;“_wp_http_referer”则是配置更新完成后返回的页面地址。

接到请求后,WordPress首先把“option_page”和“action”设置成了全局的变量,便于在后续逻辑中引用。

// wp-admin/options.php
/**
 * wp_reset_vars可以把数组中的参数从$_GET和$_POST请求中设置到全局变量中
 */
wp_reset_vars(array('action', 'option_page'));

2. 配置白名单

获取参数后的一段代码主要是权限控制和管理员帐号配置的更新,跳过。和插件配置相关的主要是后面白名单($whitelist_options)初始化代码,白名单保存了配置组及具体的配置项列表,WordPress基于此进行配置更新控制,只有在白名单里的配置项才能被更新。

//&nbsp;wp-admin/options.php
$whitelist_options = array(
	'general' => array( 'blogname', 'blogdescription', 'gmt_offset', 
			'date_format', 'time_format', 'start_of_week', 'timezone_string' )
	...
	, 'writing' => array( 'use_smilies', 'default_category', 
			'default_email_category', 'use_balanceTags', 'default_link_category', 
			'default_post_format' )
);
...
$whitelist_options = apply_filters( 'whitelist_options', $whitelist_options );
...

初始化时,WordPress已经把内置配置写到了白名单中,而插件的配置,则通过whitelist_options” Filter来添加(代码倒数第二行)。

2.1. 插件配置注册流程

插件配置的注册逻辑在wp-admin/includes/plugin.php中。

// wp-admin/includes/plugin.php
function register_setting( $option_group, $option_name, $sanitize_callback = '' ) {
	global $new_whitelist_options;
	...
	$new_whitelist_options[ $option_group ][] = $option_name;
	...
}
插件注册配置时,先把新加入的配置项写到全局的 global $new_whitelist_options变量中,然后通过 whitelist_options” Filter把插件配置写入白名单中。
// wp-admin/includes/plugin.php
function option_update_filter( $options ) {
	global $new_whitelist_options;

	if ( is_array( $new_whitelist_options ) )
		$options = add_option_whitelist( $new_whitelist_options, $options );

	return $options;
}
add_filter( 'whitelist_options', 'option_update_filter' );

具体的添加白名单逻辑则在add_option_whitelist函数中,不再赘述。

3. Update Action

白名单初始化完成后,正式进行配置的更新。

// wp-admin/options.php
/*
 * 只有'update' == $action,才处理插件配置页传入的更新请求
 */
if ( 'update' == $action ) {
	...
	// 配置组不在白名单中,直接返回错误页
	if ( !isset( $whitelist_options[ $option_page ] ) )
		wp_die( __( '<strong>ERROR</strong>: options page not found.' ) );

	if ( 'options' == $option_page ) {
		...
	} else {
		// 取出配置组内的配置列表
		$options = $whitelist_options[ $option_page ];
	}

	...

	if ( $options ) {
		// 遍历更新配置组下的配置项
		foreach ( $options as $option ) {
			...
			$option = trim( $option );
			$value = null;
			if ( isset( $_POST[ $option ] ) ) {
				$value = $_POST[ $option ];
				if ( ! is_array( $value ) )
					$value = trim( $value );
				$value = wp_unslash( $value );
			}
			update_option( $option, $value );
		}
	}

	/**
	 * 如果没有错误,则显示更新成功提示,否则显示错误信息
	 */
	if ( !count( get_settings_errors() ) )
		add_settings_error('general', 'settings_updated', __('Settings saved.'), 'updated');
	set_transient('settings_errors', get_settings_errors(), 30);

	/**
	 * 配置更新后,跳回插件配置页面,通过表单的“_wp_http_referer”参数指定
	 */
	$goback = add_query_arg( 'settings-updated', 'true',  wp_get_referer() );
	wp_redirect( $goback );
	exit;
}

4. 小结

以上即是WordPress插件配置的更新流程分析,可以看出,WordPress实现了一套复杂的配置更新机制,使得插件可以很方便的进行配置更新,但整体而言,其学习门槛不算很高,只要了解其插件扩展机制,基本都可以弄明白。

P. S. 文章转自自己在BAE的Blog(http://home4j.duapp.com/index.php/2013/08/20/wordpress-source-code-study-plugin-option-updating.html),欢迎来踩踩。

你可能感兴趣的:(更新,wordpress,配置,setting)