What is the good way to share an event with other plugins?
Example scenario: some function in my plugin saves an order. I want to allow people to know there have been a new order, but they can change nothing in my process.
Way to do this:
do_action( 'new-order' , $my_order_details )
apply_filters( 'new-order' , $my_order_details )
Is there a preferred way? In both I don’t care and don’t want that another plugin output something or change something.
Or are we missing a third hook?
Something like signal_event( 'my-event-handle', $data_about_it ) that cleans any output from the function hooked at this.
Also, you didn’t specify if you wanted the people to be notified that there was an order, or if you wanted them to be able to learn there is an order. This would affect the approach taken.
If you don’t want to use an action or a filter, maybe you could store “just enough” data in an option or transient and let other code poll for new orders from there.
Not sure if I get the idea right, as it seems that signal_event() would work absolutely the same as do_action(). It doesn’t apply any changes to a passed variable anyway. But when you set an event trigger this means that you allow other plugins to run their custom code during your execution process. This code doesn’t change your process, but it certainly can generate some output and I don’t see the way to prevent it from your hook. Is there a real need to trigger that event? Maybe it’s possible to save your result in an option and then provide a hook that fires after your output is finished?
add_action( 'new-order', 'alert_me' );
function alert_me( $customer, $item){
send_sms("Hey man, prepare $item for $customer"); //right
echo "Hey $customer, not good shopping"; // not right
}
So as I can understand do_action() is the right approach hoping that nobody “echoes” something.
Maybe it could be solved by creating a predefined function structure instead of trying to disallow particular things like output. In this case your alert function will remain a part of your code and you can just allow to filter some separate options by apply_filters(). Kinda this way:
// Your plugin
...
function alert_me( $customer, $item ) {
// What contact methods are available (in general)
$allowed_methods = array(
'send_sms' => array(
// This property can be overriden
'text' => apply_filters( 'sms_text', "Hey man, prepare $item for $customer", $item, $customer ),
// This property can be overriden
'some_property' => apply_filters('some_property', 'some_value' ),
),
'one_more_method' => array(),
);
// What contact methods are used (can be redefined by a companion plugin, too)
$methods = apply_filters( 'methods', array( 'send_sms' ) );
// Predefined process: sending SMS (if needed)
if ( array_key_exists( 'send_sms', $methods ) ) {
$props = $allowed_methods[ 'send_sms' ];
send_sms( $props['text'], $props[ 'some_property'] );
}
// Predefined process: using another method (if needed)
if ( array_key_exists( 'one_more_method', $methods ) ) {
one_more_method();
}
// Do something else...
}
register_order( $customer, $item, $credit_card_id );
greet_customer( $customer );
alert_me( $customer, $item );
// Companion plugin:
// Choosing contact methods
function my_methods() {
return array( 'send_sms', 'one_more_method' );
};
// Overriding SMS text
function my_sms_text( $text, $item, $customer ) {
return "$item for $customer! NOW!";
};
add_filter( 'methods', 'my_methods' );
add_filter( 'sms_text', 'my_sms_text' );
A little off-topic of the question asked, but, I wanted to add a note about best practices when creating new hooks (whether they’re actions or filters.) If you give them a prefix, it creates a nice safeguard to isolate your hooks against collisions. For example, the following hook:
add_action( 'new-order', 'alert_me' );
…is somewhat generic and might be found in any number of other plugins. Adding a prefix ensures that your plugin won’t be the culprit if there’s a collision.
I usually use underscored prefixes do avoid collisions. so ie. all of my UI-based plugins use “ui(plugin_acronym)_” as a prefix. Double underscore might help, too.