Make WordPress Core

source: tags/5.4/src/wp-includes/plugin.php

Last change on this file was 47198, checked in by SergeyBiryukov, 4 years ago

Code Modernization: Replace dirname( __FILE__ ) calls with __DIR__ magic constant.

This avoids the performance overhead of the function call every time dirname( __FILE__ ) was used instead of __DIR__.

This commit also includes:

  • Removing unnecessary parentheses from include/require statements. These are language constructs, not function calls.
  • Replacing include statements for several files with require_once, for consistency:
    • wp-admin/admin-header.php
    • wp-admin/admin-footer.php
    • wp-includes/version.php

Props ayeshrajans, desrosj, valentinbora, jrf, joostdevalk, netweb.
Fixes #48082.

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