[wp-trac] [WordPress Trac] #38743: Introduce add_action_once()

WordPress Trac noreply at wordpress.org
Thu Nov 10 10:26:26 UTC 2016


#38743: Introduce add_action_once()
-----------------------------+-----------------------------
 Reporter:  tfrommen         |      Owner:
     Type:  feature request  |     Status:  new
 Priority:  normal           |  Milestone:  Awaiting Review
Component:  General          |    Version:
 Severity:  normal           |   Keywords:
  Focuses:                   |
-----------------------------+-----------------------------
 Hi there.

 I was wondering if noone ever needed to add a callback to some action or
 filter hook only if it hasn't been added (potentially by someone else)
 before.

 Possible use cases are:

 * only add `my_callback` if it hasn't been added before, no matter with
 what priority;
 * only add `my_callback` if it hasn't been added before with a specific
 priority.

 Naming-wise, I'd suggest `add_action_once()` and `add_filter_once()`,
 respetively, although one could be more verbose (e.g.,
 `add_action_if_not_exists()` etc.).

 Here is a possible implementation of this:

 {{{#!php
 <?php

 function add_action_once(
     $tag,
     callable $function_to_add,
     $priority = 10,
     $accepted_args = 1,
     $check_priority = false
 ) {

     return add_filter_once( $tag, $function_to_add, $priority,
 $accepted_args, $check_priority );
 }

 function add_filter_once(
     $tag,
     callable $function_to_add,
     $priority = 10,
     $accepted_args = 1,
     $check_priority = false
 ) {

     global $wp_filter;

     if ( empty( $wp_filter[ $tag ] ) ) {
         return add_filter( $tag, $function_to_add, $priority,
 $accepted_args );
     }

     if ( false === $check_priority ) ) {
         if ( has_filter( $tag, $function_to_add ) ) {
             return false;
         }
     } else {
         foreach ( $wp_filter[ $tag ] as $functions ) {
             foreach ( $functions as $data ) {
                 if ( isset( $data['function'] ) && $function_to_add ===
 $data['function'] ) {
                     return false;
                 }
             }
         }
     }

     return add_filter( $tag, $function_to_add, $priority, $accepted_args
 );
 }
 }}}

 Yes, it is possible to check whether or not a specific callback has been
 added to an action or filter hook by using `has_filter()`. And as you can
 see, the above code uses that function internally.

 However, this would mean that your code, where you want to add a callback
 if it hasn't been added before, would have to perform `has_filter()` and
 `add_action()`/`add_filter()`.

 And secondly, by using `has_filter()`, you cannot check if a callback has
 been added with a specific priority.

 The two functions above take care of both as well.

 '''Example:'''

 {{{#!php
 <?php

 // Somewhere in your code... Maybe!
 add_filter( 'the_title', 'add_exclamation_mark', 20 );

 // Some other place, that maybe doesn't know about the place above...
 add_filter( 'the_title', 'add_exclamation_mark', 10 );

 // Yet another place...
 echo apply_filters( 'the_title', 'Hi there' );

 // Hi there!!
 }}}

 By using `add_filter_once()` (in this example withouth the last parameter
 as I'm not interested in where/when the callback gets fired), this would
 look like so:

 {{{#!php
 <?php

 // Somewhere in your code... Maybe!
 add_filter_once( 'the_title', 'add_exclamation_mark', 20 );

 // Some other place, that maybe doesn't know about the place above...
 add_filter_once( 'the_title', 'add_exclamation_mark', 10 );

 // Yet another place...
 echo apply_filters( 'the_title', 'Hi there' );

 // Hi there!
 }}}


 So, what do you think?

 Cheers,
 Thorsten

--
Ticket URL: <https://core.trac.wordpress.org/ticket/38743>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list