现在的位置: 首页 > IT运维 > 正文

WordPress插件后加载及延迟加载

2014年01月09日 IT运维 ⁄ 共 2945字 暂无评论 ⁄ 被围观 134+

wordpress插件加载顺序有时需要进行干预,因为有的函数会比较霸道,做了很多add_action会改变系统本身的一些变量,导致返回不正确,例如qTranslate会导致插件中获取语言包失败。分析wp-include/plugin.php的最后几行:

$ii=0;
	do {
		foreach( (array) current($wp_filter[$tag]) as $the_ )
			if ( !is_null($the_[\'function\']) ){
				$args[1] = $value;
				$value = call_user_func_array($the_[\'function\'], array_slice($args, 1, (int) $the_[\'accepted_args\']));
				if ($tag==\'locale\') {echo $the_[\'function\'].\'>\'.$the_[\'accepted_args\'].\'>\';print_r($args);echo $value.\'##\'.($ii++).\'##\';}
			}

	} while ( next($wp_filter[$tag]) !== false );

发现在qTranslate加载前加载的插件也会被执行qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage这个函数导致$value返回空从而导致插件中调用语言包失败,例如:

load_plugin_textdomain(\'wp-sirendingzhi\', false, dirname( plugin_basename( __FILE__ )).\'/languages/\');

顺着上述代码,跟踪到wp-include/l10n.php的 function load_plugin_textdomain 中,在函数中的这一行:

	$locale = apply_filters( \'plugin_locale\', $locale, $domain );

执行之后$locale本应返回zh_CN,却意外的返回了空值。调用的语言包名也变成了 wp-sirendingzhi-.mo,并非我们期望的wp-sirendingzhi-zh_CN.mo

解决方法,虽然我们能够修改wordpress代码,判断返回空的情况下给$locale赋值与WPLANG的值相同,但每次升级Wordpress之后还需要重写此函数,所以有效的解决办法是,在插件中控制插件加载顺序,让他比qTranslate晚加载,甚至在所有插件加载之后再加载,那么看看如下最后加载的实现方法,在加载语言包处改写如下:

include dirname( __FILE__ ) . \'/delayload.php\';
function _wpsirendingzhi_init() {
	load_plugin_textdomain(\'wp-sirendingzhi\', false, dirname( plugin_basename( __FILE__ )).\'/languages/\');
}
delayload_init( \'_wpsirendingzhi_init\' );

以下为delayload.php内容

< ?php

$GLOBALS[\'_delayload_data\'] = array( 56, __FILE__, array( \'\', ) );

if ( !class_exists( \'delayload\' ) ) :
class delayload {

	private static $candidates = array();
	private static $classes;
	private static $callbacks = array();

	private static $loaded;

	static function init( $callback = \'\' ) {
		list( $rev, $file, $classes ) = $GLOBALS[\'_delayload_data\'];

		self::$candidates[$file] = $rev;
		self::$classes[$file] = $classes;

		if ( !empty( $callback ) ) {
			self::$callbacks[$file] = $callback;

			add_action( \'activate_plugin\',  array( __CLASS__, \'delayed_activation\' ) );
		}

		if ( did_action( \'plugins_loaded\' ) )
			self::load();
		else
			add_action( \'plugins_loaded\', array( __CLASS__, \'load\' ), 9, 0 );
	}

	static function delayed_activation( $plugin ) {
		$plugin_dir = dirname( $plugin );

		if ( \'.\' == $plugin_dir )
			return;

		foreach ( self::$callbacks as $file => $callback ) {
			if ( dirname( dirname( plugin_basename( $file ) ) ) == $plugin_dir ) {
				self::load( false );
				call_user_func( $callback );
				do_action( \'delayload_activation_\' . $plugin );
				break;
			}
		}
	}

	static function load( $do_callbacks = true ) {
		arsort( self::$candidates );

		$file = key( self::$candidates );

		$path = dirname( $file ) . \'/\';

		foreach ( self::$classes[$file] as $class_name ) {
			if ( class_exists( $class_name ) )
				continue;

			$fpath = $path . substr( $class_name, 3 ) . \'.php\';
			if ( file_exists( $fpath ) ) {
				include $fpath;
				self::$loaded[] = $fpath;
			}
		}

		if ( $do_callbacks )
			foreach ( self::$callbacks as $callback )
				call_user_func( $callback );
	}
}
endif;

if ( !function_exists( \'delayload_init\' ) ) :
function delayload_init( $callback = \'\' ) {
	delayload::init( $callback );
}
endif;

以上是通过代码解决问题,当然我们也可以特意做个取不到语言的语言包文件,例如本例中,特意复制1个语言包文件,改名为 wp-sirendingzhi-.mo 。这是最快的解决办法,只能解决有木有的问题,对developer来说,用代码才是解决问题的王道。

给我留言

您必须 [ 登录 ] 才能发表留言!

×
#