WordPress: Hook Infos auslesen


Bei der Entwicklung eigener Themen oder Plugins mit WordPress ist es nützlich zu wissen, welche Callback-Funktionen an welchen Hooks hinzugefügt wurden. Viel wichtiger ist aber deren Priorität und der Typ, Action oder Filter. Denn mit add_action() und add_filter() sind sie als solche noch gar nicht endgültig definiert wie man weiter untern sehen wird. Diese Funktionen sind sogar vertauschbar, ohne einen Fehler zu generieren. So kann schnell eine Verwirrung entstehen, wenn der Programmierer die falsche Funktion benutzt. Man würde zum Beispiel anhand des Aufrufs einen Filter erwarten, der keiner ist.

In WordPress 4.7.0 wurde für die Verwaltung der Action- und Filter-Callbacks die neue WP_Hook-Klasse eingeführt. Die globale Variable $wp_filter ist seit dem ein eindimensionaler Array der WP_Hook-Klassenobjekte. Sowohl die Action- als auch Filter-Callbacks werden in diesen Objekten gespeichert. Vor der WordPress Version 4.7.0 war $wp_filter ein mehrdimensionaler Array der die Performance ziemlich belastet hat.

Was aber wenn man herausfinden möchte ob ein Hook-Callback ein Filter oder eine Aktion ist? Oder mit welcher Priorität sie ausgeführt werden? Aktionen werden beim Hinzufügen genauso behandelt wie die Filter. Man könnte einen Filter mit add_action() hinzufügen wie auch umgekehrt eine Aktion mit add_filter() und es würde keine Rolle spielen. Sie landen alle gleicherweise in dem $wp_filter-Array. Ohne Rücksicht auf den Typ. Die add_action()-Funktion ist nur ein Alias für add_filter().



Anzeige

Datei wp-includes/plugin.php:

function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    return add_filter($tag, $function_to_add, $priority, $accepted_args);
}

Der add_filter()-Aufruf in wp-includes/plugin.php:

function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
	global $wp_filter;
	if ( ! isset( $wp_filter[ $tag ] ) ) {
		$wp_filter[ $tag ] = new WP_Hook();
	}
	$wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args );
	return true;
}

Genauso ist es mit remove_action() und remove_filter().

Datei wp-includes/plugin.php:

function remove_action( $tag, $function_to_remove, $priority = 10 ) {
	return remove_filter( $tag, $function_to_remove, $priority );
}
function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
	global $wp_filter;

	$r = false;
	if ( isset( $wp_filter[ $tag ] ) ) {
		$r = $wp_filter[ $tag ]->remove_filter( $tag, $function_to_remove, $priority );
		if ( ! $wp_filter[ $tag ]->callbacks ) {
			unset( $wp_filter[ $tag ] );
		}
	}

	return $r;
}

Es gibt keinen eindeutigen Hinweis in dem WP_Hook-Klassenobjekt auf den Callback-Typ. has_action() liefert das gleiche Ergebnis wie has_filter(). Diese Abfrage ist nämlich auch nur ein Alias.

Datei wp-includes/plugin.php:

function has_action($tag, $function_to_check = false) {
	return has_filter($tag, $function_to_check);
}

Es gibt aber auch noch die globale Array-Variable $wp_actions die erst bei dem Aufruf von do_action() mit dem Hook-Tag-Namen und Aufrufanzahl gefuttert wird. Bis dahin ist der Hook-Typ undefiniert. Oder man kann grundsätzlich sagen, solange ein Hook nicht mit do_action() aufgerufen wird, ist er ein Filter!

function do_action($tag, $arg = '') {
	global $wp_filter, $wp_actions, $wp_current_filter;

	if ( ! isset($wp_actions[$tag]) )
		$wp_actions[$tag] = 1;
	else
		++$wp_actions[$tag];
        ...
}

Warum die WordPress Entwickler die Hook-Verwaltung auf diese Weise implementiert haben ist mir nicht klar. Man könnte die Hooks doch schon beim Aufruf von add_action() zum $wp_actions mit der Trigger-Anzahl 0 hinzufügen. Bei der do_action() dann nur die Aufrufanzahl hochzählen.

Auf der folgenden Seite habe ich ein Beispiel einer Funktion gezeigt, mit der man auf zweifache Weise die vorhandenen Informationen zum Hook auslesen kann.

Anzeige




Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.