ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

plugin.php (33119B)


      1 <?php
      2 /**
      3  * The plugin API is located in this file, which allows for creating actions
      4  * and filters and hooking functions, and methods. The functions or methods will
      5  * then be run when the action or filter is called.
      6  *
      7  * The API callback examples reference functions, but can be methods of classes.
      8  * To hook methods, you'll need to pass an array one of two ways.
      9  *
     10  * Any of the syntaxes explained in the PHP documentation for the
     11  * {@link https://www.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
     12  * type are valid.
     13  *
     14  * Also see the {@link https://developer.wordpress.org/plugins/ Plugin API} for
     15  * more information and examples on how to use a lot of these functions.
     16  *
     17  * This file should have no external dependencies.
     18  *
     19  * @package WordPress
     20  * @subpackage Plugin
     21  * @since 1.5.0
     22  */
     23 
     24 // Initialize the filter globals.
     25 require __DIR__ . '/class-wp-hook.php';
     26 
     27 /** @var WP_Hook[] $wp_filter */
     28 global $wp_filter;
     29 
     30 /** @var int[] $wp_actions */
     31 global $wp_actions;
     32 
     33 /** @var string[] $wp_current_filter */
     34 global $wp_current_filter;
     35 
     36 if ( $wp_filter ) {
     37 	$wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
     38 } else {
     39 	$wp_filter = array();
     40 }
     41 
     42 if ( ! isset( $wp_actions ) ) {
     43 	$wp_actions = array();
     44 }
     45 
     46 if ( ! isset( $wp_current_filter ) ) {
     47 	$wp_current_filter = array();
     48 }
     49 
     50 /**
     51  * Adds a callback function to a filter hook.
     52  *
     53  * WordPress offers filter hooks to allow plugins to modify
     54  * various types of internal data at runtime.
     55  *
     56  * A plugin can modify data by binding a callback to a filter hook. When the filter
     57  * is later applied, each bound callback is run in order of priority, and given
     58  * the opportunity to modify a value by returning a new value.
     59  *
     60  * The following example shows how a callback function is bound to a filter hook.
     61  *
     62  * Note that `$example` is passed to the callback, (maybe) modified, then returned:
     63  *
     64  *     function example_callback( $example ) {
     65  *         // Maybe modify $example in some way.
     66  *         return $example;
     67  *     }
     68  *     add_filter( 'example_filter', 'example_callback' );
     69  *
     70  * Bound callbacks can accept from none to the total number of arguments passed as parameters
     71  * in the corresponding apply_filters() call.
     72  *
     73  * In other words, if an apply_filters() call passes four total arguments, callbacks bound to
     74  * it can accept none (the same as 1) of the arguments or up to four. The important part is that
     75  * the `$accepted_args` value must reflect the number of arguments the bound callback *actually*
     76  * opted to accept. If no arguments were accepted by the callback that is considered to be the
     77  * same as accepting 1 argument. For example:
     78  *
     79  *     // Filter call.
     80  *     $value = apply_filters( 'hook', $value, $arg2, $arg3 );
     81  *
     82  *     // Accepting zero/one arguments.
     83  *     function example_callback() {
     84  *         ...
     85  *         return 'some value';
     86  *     }
     87  *     add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1.
     88  *
     89  *     // Accepting two arguments (three possible).
     90  *     function example_callback( $value, $arg2 ) {
     91  *         ...
     92  *         return $maybe_modified_value;
     93  *     }
     94  *     add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2.
     95  *
     96  * *Note:* The function will return true whether or not the callback is valid.
     97  * It is up to you to take care. This is done for optimization purposes, so
     98  * everything is as quick as possible.
     99  *
    100  * @since 0.71
    101  *
    102  * @global WP_Hook[] $wp_filter A multidimensional array of all hooks and the callbacks hooked to them.
    103  *
    104  * @param string   $hook_name     The name of the filter to add the callback to.
    105  * @param callable $callback      The callback to be run when the filter is applied.
    106  * @param int      $priority      Optional. Used to specify the order in which the functions
    107  *                                associated with a particular filter are executed.
    108  *                                Lower numbers correspond with earlier execution,
    109  *                                and functions with the same priority are executed
    110  *                                in the order in which they were added to the filter. Default 10.
    111  * @param int      $accepted_args Optional. The number of arguments the function accepts. Default 1.
    112  * @return true Always returns true.
    113  */
    114 function add_filter( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
    115 	global $wp_filter;
    116 
    117 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    118 		$wp_filter[ $hook_name ] = new WP_Hook();
    119 	}
    120 
    121 	$wp_filter[ $hook_name ]->add_filter( $hook_name, $callback, $priority, $accepted_args );
    122 
    123 	return true;
    124 }
    125 
    126 /**
    127  * Calls the callback functions that have been added to a filter hook.
    128  *
    129  * This function invokes all functions attached to filter hook `$hook_name`.
    130  * It is possible to create new filter hooks by simply calling this function,
    131  * specifying the name of the new hook using the `$hook_name` parameter.
    132  *
    133  * The function also allows for multiple additional arguments to be passed to hooks.
    134  *
    135  * Example usage:
    136  *
    137  *     // The filter callback function.
    138  *     function example_callback( $string, $arg1, $arg2 ) {
    139  *         // (maybe) modify $string.
    140  *         return $string;
    141  *     }
    142  *     add_filter( 'example_filter', 'example_callback', 10, 3 );
    143  *
    144  *     /*
    145  *      * Apply the filters by calling the 'example_callback()' function
    146  *      * that's hooked onto `example_filter` above.
    147  *      *
    148  *      * - 'example_filter' is the filter hook.
    149  *      * - 'filter me' is the value being filtered.
    150  *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
    151  *     $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 );
    152  *
    153  * @since 0.71
    154  *
    155  * @global WP_Hook[] $wp_filter         Stores all of the filters and actions.
    156  * @global string[]  $wp_current_filter Stores the list of current filters with the current one last.
    157  *
    158  * @param string $hook_name The name of the filter hook.
    159  * @param mixed  $value     The value to filter.
    160  * @param mixed  ...$args   Additional parameters to pass to the callback functions.
    161  * @return mixed The filtered value after all hooked functions are applied to it.
    162  */
    163 function apply_filters( $hook_name, $value ) {
    164 	global $wp_filter, $wp_current_filter;
    165 
    166 	$args = func_get_args();
    167 
    168 	// Do 'all' actions first.
    169 	if ( isset( $wp_filter['all'] ) ) {
    170 		$wp_current_filter[] = $hook_name;
    171 		_wp_call_all_hook( $args );
    172 	}
    173 
    174 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    175 		if ( isset( $wp_filter['all'] ) ) {
    176 			array_pop( $wp_current_filter );
    177 		}
    178 
    179 		return $value;
    180 	}
    181 
    182 	if ( ! isset( $wp_filter['all'] ) ) {
    183 		$wp_current_filter[] = $hook_name;
    184 	}
    185 
    186 	// Don't pass the tag name to WP_Hook.
    187 	array_shift( $args );
    188 
    189 	$filtered = $wp_filter[ $hook_name ]->apply_filters( $value, $args );
    190 
    191 	array_pop( $wp_current_filter );
    192 
    193 	return $filtered;
    194 }
    195 
    196 /**
    197  * Calls the callback functions that have been added to a filter hook, specifying arguments in an array.
    198  *
    199  * @since 3.0.0
    200  *
    201  * @see apply_filters() This function is identical, but the arguments passed to the
    202  *                      functions hooked to `$hook_name` are supplied using an array.
    203  *
    204  * @global WP_Hook[] $wp_filter         Stores all of the filters and actions.
    205  * @global string[]  $wp_current_filter Stores the list of current filters with the current one last.
    206  *
    207  * @param string $hook_name The name of the filter hook.
    208  * @param array  $args      The arguments supplied to the functions hooked to `$hook_name`.
    209  * @return mixed The filtered value after all hooked functions are applied to it.
    210  */
    211 function apply_filters_ref_array( $hook_name, $args ) {
    212 	global $wp_filter, $wp_current_filter;
    213 
    214 	// Do 'all' actions first.
    215 	if ( isset( $wp_filter['all'] ) ) {
    216 		$wp_current_filter[] = $hook_name;
    217 		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
    218 		_wp_call_all_hook( $all_args );
    219 	}
    220 
    221 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    222 		if ( isset( $wp_filter['all'] ) ) {
    223 			array_pop( $wp_current_filter );
    224 		}
    225 
    226 		return $args[0];
    227 	}
    228 
    229 	if ( ! isset( $wp_filter['all'] ) ) {
    230 		$wp_current_filter[] = $hook_name;
    231 	}
    232 
    233 	$filtered = $wp_filter[ $hook_name ]->apply_filters( $args[0], $args );
    234 
    235 	array_pop( $wp_current_filter );
    236 
    237 	return $filtered;
    238 }
    239 
    240 /**
    241  * Checks if any filter has been registered for a hook.
    242  *
    243  * When using the `$callback` argument, this function may return a non-boolean value
    244  * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
    245  *
    246  * @since 2.5.0
    247  *
    248  * @global WP_Hook[] $wp_filter Stores all of the filters and actions.
    249  *
    250  * @param string         $hook_name The name of the filter hook.
    251  * @param callable|false $callback  Optional. The callback to check for. Default false.
    252  * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
    253  *                  anything registered. When checking a specific function, the priority
    254  *                  of that hook is returned, or false if the function is not attached.
    255  */
    256 function has_filter( $hook_name, $callback = false ) {
    257 	global $wp_filter;
    258 
    259 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    260 		return false;
    261 	}
    262 
    263 	return $wp_filter[ $hook_name ]->has_filter( $hook_name, $callback );
    264 }
    265 
    266 /**
    267  * Removes a callback function from a filter hook.
    268  *
    269  * This can be used to remove default functions attached to a specific filter
    270  * hook and possibly replace them with a substitute.
    271  *
    272  * To remove a hook, the `$callback` and `$priority` arguments must match
    273  * when the hook was added. This goes for both filters and actions. No warning
    274  * will be given on removal failure.
    275  *
    276  * @since 1.2.0
    277  *
    278  * @global WP_Hook[] $wp_filter Stores all of the filters and actions.
    279  *
    280  * @param string   $hook_name The filter hook to which the function to be removed is hooked.
    281  * @param callable $callback  The name of the function which should be removed.
    282  * @param int      $priority  Optional. The exact priority used when adding the original
    283  *                            filter callback. Default 10.
    284  * @return bool Whether the function existed before it was removed.
    285  */
    286 function remove_filter( $hook_name, $callback, $priority = 10 ) {
    287 	global $wp_filter;
    288 
    289 	$r = false;
    290 
    291 	if ( isset( $wp_filter[ $hook_name ] ) ) {
    292 		$r = $wp_filter[ $hook_name ]->remove_filter( $hook_name, $callback, $priority );
    293 
    294 		if ( ! $wp_filter[ $hook_name ]->callbacks ) {
    295 			unset( $wp_filter[ $hook_name ] );
    296 		}
    297 	}
    298 
    299 	return $r;
    300 }
    301 
    302 /**
    303  * Removes all of the callback functions from a filter hook.
    304  *
    305  * @since 2.7.0
    306  *
    307  * @global WP_Hook[] $wp_filter Stores all of the filters and actions.
    308  *
    309  * @param string    $hook_name The filter to remove callbacks from.
    310  * @param int|false $priority  Optional. The priority number to remove them from.
    311  *                             Default false.
    312  * @return true Always returns true.
    313  */
    314 function remove_all_filters( $hook_name, $priority = false ) {
    315 	global $wp_filter;
    316 
    317 	if ( isset( $wp_filter[ $hook_name ] ) ) {
    318 		$wp_filter[ $hook_name ]->remove_all_filters( $priority );
    319 
    320 		if ( ! $wp_filter[ $hook_name ]->has_filters() ) {
    321 			unset( $wp_filter[ $hook_name ] );
    322 		}
    323 	}
    324 
    325 	return true;
    326 }
    327 
    328 /**
    329  * Retrieves the name of the current filter hook.
    330  *
    331  * @since 2.5.0
    332  *
    333  * @global string[] $wp_current_filter Stores the list of current filters with the current one last
    334  *
    335  * @return string Hook name of the current filter.
    336  */
    337 function current_filter() {
    338 	global $wp_current_filter;
    339 
    340 	return end( $wp_current_filter );
    341 }
    342 
    343 /**
    344  * Returns whether or not a filter hook is currently being processed.
    345  *
    346  * The function current_filter() only returns the most recent filter or action
    347  * being executed. did_action() returns true once the action is initially
    348  * processed.
    349  *
    350  * This function allows detection for any filter currently being executed
    351  * (regardless of whether it's the most recent filter to fire, in the case of
    352  * hooks called from hook callbacks) to be verified.
    353  *
    354  * @since 3.9.0
    355  *
    356  * @see current_filter()
    357  * @see did_action()
    358  * @global string[] $wp_current_filter Current filter.
    359  *
    360  * @param null|string $hook_name Optional. Filter hook to check. Defaults to null,
    361  *                               which checks if any filter is currently being run.
    362  * @return bool Whether the filter is currently in the stack.
    363  */
    364 function doing_filter( $hook_name = null ) {
    365 	global $wp_current_filter;
    366 
    367 	if ( null === $hook_name ) {
    368 		return ! empty( $wp_current_filter );
    369 	}
    370 
    371 	return in_array( $hook_name, $wp_current_filter, true );
    372 }
    373 
    374 /**
    375  * Adds a callback function to an action hook.
    376  *
    377  * Actions are the hooks that the WordPress core launches at specific points
    378  * during execution, or when specific events occur. Plugins can specify that
    379  * one or more of its PHP functions are executed at these points, using the
    380  * Action API.
    381  *
    382  * @since 1.2.0
    383  *
    384  * @param string   $hook_name       The name of the action to add the callback to.
    385  * @param callable $callback        The callback to be run when the action is called.
    386  * @param int      $priority        Optional. Used to specify the order in which the functions
    387  *                                  associated with a particular action are executed.
    388  *                                  Lower numbers correspond with earlier execution,
    389  *                                  and functions with the same priority are executed
    390  *                                  in the order in which they were added to the action. Default 10.
    391  * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
    392  * @return true Always returns true.
    393  */
    394 function add_action( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
    395 	return add_filter( $hook_name, $callback, $priority, $accepted_args );
    396 }
    397 
    398 /**
    399  * Calls the callback functions that have been added to an action hook.
    400  *
    401  * This function invokes all functions attached to action hook `$hook_name`.
    402  * It is possible to create new action hooks by simply calling this function,
    403  * specifying the name of the new hook using the `$hook_name` parameter.
    404  *
    405  * You can pass extra arguments to the hooks, much like you can with `apply_filters()`.
    406  *
    407  * Example usage:
    408  *
    409  *     // The action callback function.
    410  *     function example_callback( $arg1, $arg2 ) {
    411  *         // (maybe) do something with the args.
    412  *     }
    413  *     add_action( 'example_action', 'example_callback', 10, 2 );
    414  *
    415  *     /*
    416  *      * Trigger the actions by calling the 'example_callback()' function
    417  *      * that's hooked onto `example_action` above.
    418  *      *
    419  *      * - 'example_action' is the action hook.
    420  *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
    421  *     $value = do_action( 'example_action', $arg1, $arg2 );
    422  *
    423  * @since 1.2.0
    424  * @since 5.3.0 Formalized the existing and already documented `...$arg` parameter
    425  *              by adding it to the function signature.
    426  *
    427  * @global WP_Hook[] $wp_filter         Stores all of the filters and actions.
    428  * @global int[]     $wp_actions        Stores the number of times each action was triggered.
    429  * @global string[]  $wp_current_filter Stores the list of current filters with the current one last.
    430  *
    431  * @param string $hook_name The name of the action to be executed.
    432  * @param mixed  ...$arg    Optional. Additional arguments which are passed on to the
    433  *                          functions hooked to the action. Default empty.
    434  */
    435 function do_action( $hook_name, ...$arg ) {
    436 	global $wp_filter, $wp_actions, $wp_current_filter;
    437 
    438 	if ( ! isset( $wp_actions[ $hook_name ] ) ) {
    439 		$wp_actions[ $hook_name ] = 1;
    440 	} else {
    441 		++$wp_actions[ $hook_name ];
    442 	}
    443 
    444 	// Do 'all' actions first.
    445 	if ( isset( $wp_filter['all'] ) ) {
    446 		$wp_current_filter[] = $hook_name;
    447 		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
    448 		_wp_call_all_hook( $all_args );
    449 	}
    450 
    451 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    452 		if ( isset( $wp_filter['all'] ) ) {
    453 			array_pop( $wp_current_filter );
    454 		}
    455 
    456 		return;
    457 	}
    458 
    459 	if ( ! isset( $wp_filter['all'] ) ) {
    460 		$wp_current_filter[] = $hook_name;
    461 	}
    462 
    463 	if ( empty( $arg ) ) {
    464 		$arg[] = '';
    465 	} elseif ( is_array( $arg[0] ) && 1 === count( $arg[0] ) && isset( $arg[0][0] ) && is_object( $arg[0][0] ) ) {
    466 		// Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`.
    467 		$arg[0] = $arg[0][0];
    468 	}
    469 
    470 	$wp_filter[ $hook_name ]->do_action( $arg );
    471 
    472 	array_pop( $wp_current_filter );
    473 }
    474 
    475 /**
    476  * Calls the callback functions that have been added to an action hook, specifying arguments in an array.
    477  *
    478  * @since 2.1.0
    479  *
    480  * @see do_action() This function is identical, but the arguments passed to the
    481  *                  functions hooked to `$hook_name` are supplied using an array.
    482  *
    483  * @global WP_Hook[] $wp_filter         Stores all of the filters and actions.
    484  * @global int[]     $wp_actions        Stores the number of times each action was triggered.
    485  * @global string[]  $wp_current_filter Stores the list of current filters with the current one last.
    486  *
    487  * @param string $hook_name The name of the action to be executed.
    488  * @param array  $args      The arguments supplied to the functions hooked to `$hook_name`.
    489  */
    490 function do_action_ref_array( $hook_name, $args ) {
    491 	global $wp_filter, $wp_actions, $wp_current_filter;
    492 
    493 	if ( ! isset( $wp_actions[ $hook_name ] ) ) {
    494 		$wp_actions[ $hook_name ] = 1;
    495 	} else {
    496 		++$wp_actions[ $hook_name ];
    497 	}
    498 
    499 	// Do 'all' actions first.
    500 	if ( isset( $wp_filter['all'] ) ) {
    501 		$wp_current_filter[] = $hook_name;
    502 		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
    503 		_wp_call_all_hook( $all_args );
    504 	}
    505 
    506 	if ( ! isset( $wp_filter[ $hook_name ] ) ) {
    507 		if ( isset( $wp_filter['all'] ) ) {
    508 			array_pop( $wp_current_filter );
    509 		}
    510 
    511 		return;
    512 	}
    513 
    514 	if ( ! isset( $wp_filter['all'] ) ) {
    515 		$wp_current_filter[] = $hook_name;
    516 	}
    517 
    518 	$wp_filter[ $hook_name ]->do_action( $args );
    519 
    520 	array_pop( $wp_current_filter );
    521 }
    522 
    523 /**
    524  * Checks if any action has been registered for a hook.
    525  *
    526  * When using the `$callback` argument, this function may return a non-boolean value
    527  * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
    528  *
    529  * @since 2.5.0
    530  *
    531  * @see has_filter() has_action() is an alias of has_filter().
    532  *
    533  * @param string         $hook_name The name of the action hook.
    534  * @param callable|false $callback  Optional. The callback to check for. Default false.
    535  * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
    536  *                  anything registered. When checking a specific function, the priority
    537  *                  of that hook is returned, or false if the function is not attached.
    538  */
    539 function has_action( $hook_name, $callback = false ) {
    540 	return has_filter( $hook_name, $callback );
    541 }
    542 
    543 /**
    544  * Removes a callback function from an action hook.
    545  *
    546  * This can be used to remove default functions attached to a specific action
    547  * hook and possibly replace them with a substitute.
    548  *
    549  * To remove a hook, the `$callback` and `$priority` arguments must match
    550  * when the hook was added. This goes for both filters and actions. No warning
    551  * will be given on removal failure.
    552  *
    553  * @since 1.2.0
    554  *
    555  * @param string   $hook_name The action hook to which the function to be removed is hooked.
    556  * @param callable $callback  The name of the function which should be removed.
    557  * @param int      $priority  Optional. The exact priority used when adding the original
    558  *                            action callback. Default 10.
    559  * @return bool Whether the function is removed.
    560  */
    561 function remove_action( $hook_name, $callback, $priority = 10 ) {
    562 	return remove_filter( $hook_name, $callback, $priority );
    563 }
    564 
    565 /**
    566  * Removes all of the callback functions from an action hook.
    567  *
    568  * @since 2.7.0
    569  *
    570  * @param string    $hook_name The action to remove callbacks from.
    571  * @param int|false $priority  Optional. The priority number to remove them from.
    572  *                             Default false.
    573  * @return true Always returns true.
    574  */
    575 function remove_all_actions( $hook_name, $priority = false ) {
    576 	return remove_all_filters( $hook_name, $priority );
    577 }
    578 
    579 /**
    580  * Retrieves the name of the current action hook.
    581  *
    582  * @since 3.9.0
    583  *
    584  * @return string Hook name of the current action.
    585  */
    586 function current_action() {
    587 	return current_filter();
    588 }
    589 
    590 /**
    591  * Returns whether or not an action hook is currently being processed.
    592  *
    593  * @since 3.9.0
    594  *
    595  * @param string|null $hook_name Optional. Action hook to check. Defaults to null,
    596  *                               which checks if any action is currently being run.
    597  * @return bool Whether the action is currently in the stack.
    598  */
    599 function doing_action( $hook_name = null ) {
    600 	return doing_filter( $hook_name );
    601 }
    602 
    603 /**
    604  * Retrieves the number of times an action has been fired during the current request.
    605  *
    606  * @since 2.1.0
    607  *
    608  * @global int[] $wp_actions Stores the number of times each action was triggered.
    609  *
    610  * @param string $hook_name The name of the action hook.
    611  * @return int The number of times the action hook has been fired.
    612  */
    613 function did_action( $hook_name ) {
    614 	global $wp_actions;
    615 
    616 	if ( ! isset( $wp_actions[ $hook_name ] ) ) {
    617 		return 0;
    618 	}
    619 
    620 	return $wp_actions[ $hook_name ];
    621 }
    622 
    623 /**
    624  * Fires functions attached to a deprecated filter hook.
    625  *
    626  * When a filter hook is deprecated, the apply_filters() call is replaced with
    627  * apply_filters_deprecated(), which triggers a deprecation notice and then fires
    628  * the original filter hook.
    629  *
    630  * Note: the value and extra arguments passed to the original apply_filters() call
    631  * must be passed here to `$args` as an array. For example:
    632  *
    633  *     // Old filter.
    634  *     return apply_filters( 'wpdocs_filter', $value, $extra_arg );
    635  *
    636  *     // Deprecated.
    637  *     return apply_filters_deprecated( 'wpdocs_filter', array( $value, $extra_arg ), '4.9.0', 'wpdocs_new_filter' );
    638  *
    639  * @since 4.6.0
    640  *
    641  * @see _deprecated_hook()
    642  *
    643  * @param string $hook_name   The name of the filter hook.
    644  * @param array  $args        Array of additional function arguments to be passed to apply_filters().
    645  * @param string $version     The version of WordPress that deprecated the hook.
    646  * @param string $replacement Optional. The hook that should have been used. Default empty.
    647  * @param string $message     Optional. A message regarding the change. Default empty.
    648  */
    649 function apply_filters_deprecated( $hook_name, $args, $version, $replacement = '', $message = '' ) {
    650 	if ( ! has_filter( $hook_name ) ) {
    651 		return $args[0];
    652 	}
    653 
    654 	_deprecated_hook( $hook_name, $version, $replacement, $message );
    655 
    656 	return apply_filters_ref_array( $hook_name, $args );
    657 }
    658 
    659 /**
    660  * Fires functions attached to a deprecated action hook.
    661  *
    662  * When an action hook is deprecated, the do_action() call is replaced with
    663  * do_action_deprecated(), which triggers a deprecation notice and then fires
    664  * the original hook.
    665  *
    666  * @since 4.6.0
    667  *
    668  * @see _deprecated_hook()
    669  *
    670  * @param string $hook_name   The name of the action hook.
    671  * @param array  $args        Array of additional function arguments to be passed to do_action().
    672  * @param string $version     The version of WordPress that deprecated the hook.
    673  * @param string $replacement Optional. The hook that should have been used. Default empty.
    674  * @param string $message     Optional. A message regarding the change. Default empty.
    675  */
    676 function do_action_deprecated( $hook_name, $args, $version, $replacement = '', $message = '' ) {
    677 	if ( ! has_action( $hook_name ) ) {
    678 		return;
    679 	}
    680 
    681 	_deprecated_hook( $hook_name, $version, $replacement, $message );
    682 
    683 	do_action_ref_array( $hook_name, $args );
    684 }
    685 
    686 //
    687 // Functions for handling plugins.
    688 //
    689 
    690 /**
    691  * Gets the basename of a plugin.
    692  *
    693  * This method extracts the name of a plugin from its filename.
    694  *
    695  * @since 1.5.0
    696  *
    697  * @global array $wp_plugin_paths
    698  *
    699  * @param string $file The filename of plugin.
    700  * @return string The name of a plugin.
    701  */
    702 function plugin_basename( $file ) {
    703 	global $wp_plugin_paths;
    704 
    705 	// $wp_plugin_paths contains normalized paths.
    706 	$file = wp_normalize_path( $file );
    707 
    708 	arsort( $wp_plugin_paths );
    709 
    710 	foreach ( $wp_plugin_paths as $dir => $realdir ) {
    711 		if ( strpos( $file, $realdir ) === 0 ) {
    712 			$file = $dir . substr( $file, strlen( $realdir ) );
    713 		}
    714 	}
    715 
    716 	$plugin_dir    = wp_normalize_path( WP_PLUGIN_DIR );
    717 	$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
    718 
    719 	// Get relative path from plugins directory.
    720 	$file = preg_replace( '#^' . preg_quote( $plugin_dir, '#' ) . '/|^' . preg_quote( $mu_plugin_dir, '#' ) . '/#', '', $file );
    721 	$file = trim( $file, '/' );
    722 	return $file;
    723 }
    724 
    725 /**
    726  * Register a plugin's real path.
    727  *
    728  * This is used in plugin_basename() to resolve symlinked paths.
    729  *
    730  * @since 3.9.0
    731  *
    732  * @see wp_normalize_path()
    733  *
    734  * @global array $wp_plugin_paths
    735  *
    736  * @param string $file Known path to the file.
    737  * @return bool Whether the path was able to be registered.
    738  */
    739 function wp_register_plugin_realpath( $file ) {
    740 	global $wp_plugin_paths;
    741 
    742 	// Normalize, but store as static to avoid recalculation of a constant value.
    743 	static $wp_plugin_path = null, $wpmu_plugin_path = null;
    744 
    745 	if ( ! isset( $wp_plugin_path ) ) {
    746 		$wp_plugin_path   = wp_normalize_path( WP_PLUGIN_DIR );
    747 		$wpmu_plugin_path = wp_normalize_path( WPMU_PLUGIN_DIR );
    748 	}
    749 
    750 	$plugin_path     = wp_normalize_path( dirname( $file ) );
    751 	$plugin_realpath = wp_normalize_path( dirname( realpath( $file ) ) );
    752 
    753 	if ( $plugin_path === $wp_plugin_path || $plugin_path === $wpmu_plugin_path ) {
    754 		return false;
    755 	}
    756 
    757 	if ( $plugin_path !== $plugin_realpath ) {
    758 		$wp_plugin_paths[ $plugin_path ] = $plugin_realpath;
    759 	}
    760 
    761 	return true;
    762 }
    763 
    764 /**
    765  * Get the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in.
    766  *
    767  * @since 2.8.0
    768  *
    769  * @param string $file The filename of the plugin (__FILE__).
    770  * @return string the filesystem path of the directory that contains the plugin.
    771  */
    772 function plugin_dir_path( $file ) {
    773 	return trailingslashit( dirname( $file ) );
    774 }
    775 
    776 /**
    777  * Get the URL directory path (with trailing slash) for the plugin __FILE__ passed in.
    778  *
    779  * @since 2.8.0
    780  *
    781  * @param string $file The filename of the plugin (__FILE__).
    782  * @return string the URL path of the directory that contains the plugin.
    783  */
    784 function plugin_dir_url( $file ) {
    785 	return trailingslashit( plugins_url( '', $file ) );
    786 }
    787 
    788 /**
    789  * Set the activation hook for a plugin.
    790  *
    791  * When a plugin is activated, the action 'activate_PLUGINNAME' hook is
    792  * called. In the name of this hook, PLUGINNAME is replaced with the name
    793  * of the plugin, including the optional subdirectory. For example, when the
    794  * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
    795  * the name of this hook will become 'activate_sampleplugin/sample.php'.
    796  *
    797  * When the plugin consists of only one file and is (as by default) located at
    798  * wp-content/plugins/sample.php the name of this hook will be
    799  * 'activate_sample.php'.
    800  *
    801  * @since 2.0.0
    802  *
    803  * @param string   $file     The filename of the plugin including the path.
    804  * @param callable $callback The function hooked to the 'activate_PLUGIN' action.
    805  */
    806 function register_activation_hook( $file, $callback ) {
    807 	$file = plugin_basename( $file );
    808 	add_action( 'activate_' . $file, $callback );
    809 }
    810 
    811 /**
    812  * Sets the deactivation hook for a plugin.
    813  *
    814  * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is
    815  * called. In the name of this hook, PLUGINNAME is replaced with the name
    816  * of the plugin, including the optional subdirectory. For example, when the
    817  * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
    818  * the name of this hook will become 'deactivate_sampleplugin/sample.php'.
    819  *
    820  * When the plugin consists of only one file and is (as by default) located at
    821  * wp-content/plugins/sample.php the name of this hook will be
    822  * 'deactivate_sample.php'.
    823  *
    824  * @since 2.0.0
    825  *
    826  * @param string   $file     The filename of the plugin including the path.
    827  * @param callable $callback The function hooked to the 'deactivate_PLUGIN' action.
    828  */
    829 function register_deactivation_hook( $file, $callback ) {
    830 	$file = plugin_basename( $file );
    831 	add_action( 'deactivate_' . $file, $callback );
    832 }
    833 
    834 /**
    835  * Sets the uninstallation hook for a plugin.
    836  *
    837  * Registers the uninstall hook that will be called when the user clicks on the
    838  * uninstall link that calls for the plugin to uninstall itself. The link won't
    839  * be active unless the plugin hooks into the action.
    840  *
    841  * The plugin should not run arbitrary code outside of functions, when
    842  * registering the uninstall hook. In order to run using the hook, the plugin
    843  * will have to be included, which means that any code laying outside of a
    844  * function will be run during the uninstallation process. The plugin should not
    845  * hinder the uninstallation process.
    846  *
    847  * If the plugin can not be written without running code within the plugin, then
    848  * the plugin should create a file named 'uninstall.php' in the base plugin
    849  * folder. This file will be called, if it exists, during the uninstallation process
    850  * bypassing the uninstall hook. The plugin, when using the 'uninstall.php'
    851  * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before
    852  * executing.
    853  *
    854  * @since 2.7.0
    855  *
    856  * @param string   $file     Plugin file.
    857  * @param callable $callback The callback to run when the hook is called. Must be
    858  *                           a static method or function.
    859  */
    860 function register_uninstall_hook( $file, $callback ) {
    861 	if ( is_array( $callback ) && is_object( $callback[0] ) ) {
    862 		_doing_it_wrong( __FUNCTION__, __( 'Only a static class method or function can be used in an uninstall hook.' ), '3.1.0' );
    863 		return;
    864 	}
    865 
    866 	/*
    867 	 * The option should not be autoloaded, because it is not needed in most
    868 	 * cases. Emphasis should be put on using the 'uninstall.php' way of
    869 	 * uninstalling the plugin.
    870 	 */
    871 	$uninstallable_plugins = (array) get_option( 'uninstall_plugins' );
    872 	$plugin_basename       = plugin_basename( $file );
    873 
    874 	if ( ! isset( $uninstallable_plugins[ $plugin_basename ] ) || $uninstallable_plugins[ $plugin_basename ] !== $callback ) {
    875 		$uninstallable_plugins[ $plugin_basename ] = $callback;
    876 		update_option( 'uninstall_plugins', $uninstallable_plugins );
    877 	}
    878 }
    879 
    880 /**
    881  * Calls the 'all' hook, which will process the functions hooked into it.
    882  *
    883  * The 'all' hook passes all of the arguments or parameters that were used for
    884  * the hook, which this function was called for.
    885  *
    886  * This function is used internally for apply_filters(), do_action(), and
    887  * do_action_ref_array() and is not meant to be used from outside those
    888  * functions. This function does not check for the existence of the all hook, so
    889  * it will fail unless the all hook exists prior to this function call.
    890  *
    891  * @since 2.5.0
    892  * @access private
    893  *
    894  * @global WP_Hook[] $wp_filter Stores all of the filters and actions.
    895  *
    896  * @param array $args The collected parameters from the hook that was called.
    897  */
    898 function _wp_call_all_hook( $args ) {
    899 	global $wp_filter;
    900 
    901 	$wp_filter['all']->do_all_hook( $args );
    902 }
    903 
    904 /**
    905  * Builds Unique ID for storage and retrieval.
    906  *
    907  * The old way to serialize the callback caused issues and this function is the
    908  * solution. It works by checking for objects and creating a new property in
    909  * the class to keep track of the object and new objects of the same class that
    910  * need to be added.
    911  *
    912  * It also allows for the removal of actions and filters for objects after they
    913  * change class properties. It is possible to include the property $wp_filter_id
    914  * in your class and set it to "null" or a number to bypass the workaround.
    915  * However this will prevent you from adding new classes and any new classes
    916  * will overwrite the previous hook by the same class.
    917  *
    918  * Functions and static method callbacks are just returned as strings and
    919  * shouldn't have any speed penalty.
    920  *
    921  * @link https://core.trac.wordpress.org/ticket/3875
    922  *
    923  * @since 2.2.3
    924  * @since 5.3.0 Removed workarounds for spl_object_hash().
    925  *              `$hook_name` and `$priority` are no longer used,
    926  *              and the function always returns a string.
    927  * @access private
    928  *
    929  * @param string   $hook_name Unused. The name of the filter to build ID for.
    930  * @param callable $callback  The function to generate ID for.
    931  * @param int      $priority  Unused. The order in which the functions
    932  *                            associated with a particular action are executed.
    933  * @return string Unique function ID for usage as array key.
    934  */
    935 function _wp_filter_build_unique_id( $hook_name, $callback, $priority ) {
    936 	if ( is_string( $callback ) ) {
    937 		return $callback;
    938 	}
    939 
    940 	if ( is_object( $callback ) ) {
    941 		// Closures are currently implemented as objects.
    942 		$callback = array( $callback, '' );
    943 	} else {
    944 		$callback = (array) $callback;
    945 	}
    946 
    947 	if ( is_object( $callback[0] ) ) {
    948 		// Object class calling.
    949 		return spl_object_hash( $callback[0] ) . $callback[1];
    950 	} elseif ( is_string( $callback[0] ) ) {
    951 		// Static calling.
    952 		return $callback[0] . '::' . $callback[1];
    953 	}
    954 }