Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Enables action and filter callbacks to be executed exactly once via the WordPress Plugin API. https://engineering.growella.com/one-time-callbacks-wordpress-plugin-api/
<?php
/**
* Registers the "One time hook" functionality.
*
* Note that this file is intentionally in the *global* namespace!
*
* @author Growella
* @license MIT
*/
if ( ! function_exists( 'add_action_once' ) ) {
/**
* Register an action to run exactly one time.
*
* The arguments match that of add_action(), but this function will also register a second
* callback designed to remove the first immediately after it runs.
*
* @param string $hook The action name.
* @param callable $callback The callback function.
* @param int $priority Optional. The priority at which the callback should be executed.
* Default is 10.
* @param int $args Optional. The number of arguments expected by the callback function.
* Default is 1.
* @return bool Like add_action(), this function always returns true.
*/
function add_action_once( $hook, $callback, $priority = 10, $args = 1 ) {
$singular = function () use ( $hook, $callback, $priority, $args, &$singular ) {
call_user_func_array( $callback, func_get_args() );
remove_action( $hook, $singular, $priority, $args );
};
return add_action( $hook, $singular, $priority, $args );
}
}
if ( ! function_exists( 'add_filter_once' ) ) {
/**
* Register a filter to run exactly one time.
*
* The arguments match that of add_filter(), but this function will also register a second
* callback designed to remove the first immediately after it runs.
*
* @param string $hook The filter name.
* @param callable $callback The callback function.
* @param int $priority Optional. The priority at which the callback should be executed.
* Default is 10.
* @param int $args Optional. The number of arguments expected by the callback function.
* Default is 1.
* @return bool Like add_filter(), this function always returns true.
*/
function add_filter_once( $hook, $callback, $priority = 10, $args = 1 ) {
$singular = function () use ( $hook, $callback, $priority, $args, &$singular ) {
call_user_func_array( $callback, func_get_args() );
remove_filter( $hook, $singular, $priority, $args );
};
return add_filter( $hook, $singular, $priority, $args );
}
}
@kimhf

This comment has been minimized.

Show comment
Hide comment
@kimhf

kimhf May 8, 2018

Very nice solution. There is one issue when one or more add_action_once is called inside the callback. Ends with a crash in my case. Moving remove_action and remove_filter above call_user_func_array seems to solve it.

kimhf commented May 8, 2018

Very nice solution. There is one issue when one or more add_action_once is called inside the callback. Ends with a crash in my case. Moving remove_action and remove_filter above call_user_func_array seems to solve it.

@thefrosty

This comment has been minimized.

Show comment
Hide comment
@thefrosty

thefrosty Jul 11, 2018

The remove_* functions only use 3 parameters, so passing the args array isn't needed.

thefrosty commented Jul 11, 2018

The remove_* functions only use 3 parameters, so passing the args array isn't needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment