Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Last active June 17, 2021 04:42
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mikeschinkel/5846950 to your computer and use it in GitHub Desktop.
Save mikeschinkel/5846950 to your computer and use it in GitHub Desktop.
Classes providing "hooks" (actions and filters) that work with WordPress or free-standing PHP-based apps.
<?php
class Custom_Hooks {
/**
* Adds a filter hook for an object
*
* Custom_Hooks::add_filter( 'filter_data', array( $this, 'filter_data' ) );
* Custom_Hooks::add_filter( 'filter_data', array( $this, 'filter_data' ), 11 );
* Custom_Hooks::add_filter( 'filter_data', 'special_func' );
* Custom_Hooks::add_filter( 'filter_data', 'special_func', 11 );
* Custom_Hooks::add_filter( 'filter_data', array( __CLASS__, 'filter_data' ) );
* Custom_Hooks::add_filter( 'filter_data', array( __CLASS__, 'filter_data' ), 11 );
* Custom_Hooks::add_filter( 'filter_data', array( new SpecialClass(), 'filter_data' ) );
* Custom_Hooks::add_filter( 'filter_data', array( new SpecialClass(), 'filter_data' ), 11 );
*
* @param string $filter_name
* @param array|string $callable
* @param int $priority
*
* @return mixed
*/
static function add_filter( $filter_name, $callable, $priority = 10 ) {
if ( is_string( $callable ) ) {
$function = "{$callable}()";
} else if ( is_array( $callable ) ) {
if ( is_string( $callable[0] ) ) {
$function = "{$callable[0]}::{$callable[1]}()";
} else if ( is_object( $callable[0] ) ) {
$object_hash = spl_object_hash( $callable[0] );
$function = "{$object_hash}->{$callable[1]}()";
}
}
self::$_filters[$filter_name][$function][$priority][] = $callable;
}
/**
* Adds a filter hook for an object
*
* Custom_Hooks::add_action( 'process_action', array( $this, 'process_action' ) );
* Custom_Hooks::add_action( 'process_action', array( $this, 'process_action' ), 11 );
* Custom_Hooks::add_action( 'process_action', 'special_func' );
* Custom_Hooks::add_action( 'process_action', 'special_func', 11 );
* Custom_Hooks::add_action( 'process_action', array( __CLASS__, 'process_action' ) );
* Custom_Hooks::add_action( 'process_action', array( __CLASS__, 'process_action' ), 11 );
* Custom_Hooks::add_action( 'process_action', array( new SpecialClass(), 'process_action' ) );
* Custom_Hooks::add_action( 'process_action', array( new SpecialClass(), 'process_action' ), 11 );
*
* @param string $action_name
* @param array|string $callable
* @param int $priority
*
* @return mixed
*/
static function add_action( $action_name, $callable, $priority = 10 ) {
self::add_filter( $action_name, $callable, $priority );
}
/**
* Return a list of filters
*
* @param string $filter_name
*
* @return mixed
*/
static function get_filters( $filter_name ) {
return isset( self::$_filters[$filter_name] ) ? self::$_filters[$filter_name] : false;
}
}
<?php
class Hooks_Base {
/**
* Adds a filter hook for an object
*
* $this->add_filter( 'filter_result' );
* $this->add_filter( 'filter_result', 11 );
* $this->add_filter( 'filter_result', 'special_func' );
* $this->add_filter( 'filter_result', 'special_func', 11 );
* $this->add_filter( 'filter_result', array( __CLASS__, 'class_func' ) );
* $this->add_filter( 'filter_result', array( __CLASS__, 'class_func' ), 11 );
* $this->add_filter( 'filter_result', new SpecialClass() );
* $this->add_filter( 'filter_result', new SpecialClass(), 11 );
*
* @param string $filter_name
* @param string|array|object|int $callable_object_or_priority Array Callable, String Callable, Class w/Named Filter or Priority
* @param int|null $priority
*
* @return mixed
*/
function add_filter( $filter_name, $callable_object_or_priority = null, $priority = null ) {
list( $callable, $priority ) = $this->_parse_callable_args( $filter_name, $callable_object_or_priority, $priority );
if ( defined( 'WP_CONTENT_DIR') ) {
$filter_name = spl_object_hash( $this ) . "->{$filter_name}()";
add_filter( $filter_name, $callable, $priority, 99 );
} else {
Custom_Hooks::add_filter( $filter_name, $callable, $priority );
}
return true;
}
/**
* Adds a filter hook for an object
*
* $this->add_action( 'process_action' );
* $this->add_action( 'process_action', 11 );
* $this->add_action( 'process_action', 'special_func' );
* $this->add_action( 'process_action', 'special_func', 11 );
* $this->add_action( 'process_action', array( __CLASS__, 'class_func' ) );
* $this->add_action( 'process_action', array( __CLASS__, 'class_func' ), 11 );
* $this->add_action( 'process_action', new SpecialClass() );
* $this->add_action( 'process_action', new SpecialClass(), 11 );
*
* @param string $action_name
* @param string|array|object|int $callable_object_or_priority Array Callable, String Callable, Class w/Named Action or Priority
* @param int|null $priority
*
* @return mixed
*/
function add_action( $action_name, $callable_object_or_priority = null, $priority = null ) {
list( $callable, $priority ) = $this->_parse_callable_args( $action_name, $callable_object_or_priority, $priority );
if ( defined( 'WP_CONTENT_DIR') ) {
add_action( $this->_hash_hook_name( $action_name ), $callable, $priority, 99 );
} else {
Custom_Hooks::add_action( $action_name, $callable, $priority );
}
}
/**
* @param string $filter_name
* @param mixed $value
*
* @return mixed
*/
function apply_filters( $filter_name, $value ) {
if ( defined( 'WP_CONTENT_DIR') ) {
$args = func_get_args();
$args[0] = $this->_hash_hook_name( $filter_name );
$value = call_user_func_array( 'apply_filters', $args );
} else {
$filters = RESTian::get_filters( $filter_name );
if ( count( $filters ) ) {
$args = func_get_args();
array_shift( $args );
foreach( $filters as $function ) {
/**
* Sort by priorty
*/
ksort( $function );
foreach( $function as $priority ) {
foreach( $priority as $callable ) {
$value = call_user_func_array( $callable, $args );
}
}
}
}
}
return $value;
}
/**
* @param string $action_name
*
* @return mixed
*/
function do_action( $action_name ) {
if ( defined( 'WP_CONTENT_DIR') ) {
$args = func_get_args();
$args[0] = $this->_hash_hook_name( $action_name );
call_user_func_array( 'do_action', $args );
} else {
call_user_func_array( array( $this, 'apply_filters' ), func_get_args() );
}
}
/**
* Parse args for $this->add_action() and $this->add_filter().
*
* @param string $filter_name
* @param string|array|object|int $callable_object_or_priority Array Callable, String Callable, Class w/Named Action or Priority
* @param int|null $priority
*
* @return array
*/
private function _parse_callable_args( $filter_name, $callable_object_or_priority = null, $priority = null ) {
if ( ! $callable_object_or_priority ) {
$callable = array( $this, "_{$filter_name}" );
} else if ( is_numeric( $callable_object_or_priority ) ) {
$priority = $callable_object_or_priority;
} else if ( is_string( $callable_object_or_priority ) ) {
$callable = array( $this, $callable_object_or_priority );
} else if ( is_array( $callable_object_or_priority ) ) {
$callable = $callable_object_or_priority;
} else if ( is_object( $callable_object_or_priority ) ) {
$callable = array( $callable_object_or_priority, "_{$filter_name}" );
}
if ( is_null( $priority ) ) {
$priority = 10;
}
return array( $callable, $priority );
}
private function _hash_hook_name( $hook_name ) {
return spl_object_hash( $this ) . "->{$hook_name}()";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment