読者です 読者をやめる 読者になる 読者になる

add_filter関数とapply_filters関数

WordPress

出力内容に対してフィルター(任意の処理)をかけることができる関数にapply_filterがある。この関数はプラグインを作成するときに使うことになるが、本体のソースコードでも使われている。ソースコードを読むためにはこのapply_filterとdo_actionの挙動を理解する必要がありそうだ。とりあえずソースコードを読みながら適当にメモする。

apply_filter関数の定義はplugin.phpで書かれており、下記の内容になる。

<?php
function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
	global $wp_filter, $merged_filters;

	$idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
	$wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
	unset( $merged_filters[ $tag ] );
	return true;
}
?>

この関数の処理内容は、

 (1)グローバル変数として$wp_filterと$merged_filtersを使うことを宣言。

 (2)追加するフィルター関数にidを振る。(想定)

 (3)グローバル変数の$wp_filter配列に追加するフィルター関数を保存する。

 (4)$merged_filters配列の$tag要素をクリアする。

となっており、グローバル変数の$wp_filter配列に書きこむことが目的のようだ。

そして次はapply_filters関数。

<?php
function apply_filters($tag, $value) {
	global $wp_filter, $merged_filters, $wp_current_filter;

	$args = array();

        // フィルタータグallに対して登録されているフィルター関数を実行する。
	// Do 'all' actions first
	if ( isset($wp_filter['all']) ) {
		$wp_current_filter[] = $tag;
		$args = func_get_args();
		_wp_call_all_hook($args);
	}

        
	if ( !isset($wp_filter[$tag]) ) {
		if ( isset($wp_filter['all']) )
			array_pop($wp_current_filter);
		return $value;
	}

	if ( !isset($wp_filter['all']) )
		$wp_current_filter[] = $tag;

	// Sort
	if ( !isset( $merged_filters[ $tag ] ) ) {
		ksort($wp_filter[$tag]);
		$merged_filters[ $tag ] = true;
	}

	reset( $wp_filter[ $tag ] );

        // $argsが空だったら引数のリストを配列で$argsに保存する。
	if ( empty($args) )
		$args = func_get_args();

	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']));
			}

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

	array_pop( $wp_current_filter );

	return $value;
}
?>