run:R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:51
R W Run
DIR
2026-03-11 16:18:51
R W Run
23.8 KB
2026-03-11 16:18:51
R W Run
7.8 KB
2026-03-11 16:18:52
R W Run
36.1 KB
2026-03-11 16:18:51
R W Run
11.9 KB
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:52
R W Run
28.6 KB
2026-03-11 16:18:51
R W Run
316 By
2026-03-11 16:18:51
R W Run
12.9 KB
2026-03-11 16:18:51
R W Run
61.02 KB
2026-03-11 16:18:52
R W Run
15 KB
2026-03-11 16:18:51
R W Run
112.05 KB
2026-03-11 16:18:51
R W Run
12.47 KB
2026-03-11 16:18:51
R W Run
15.07 KB
2026-03-11 16:18:52
R W Run
9.84 KB
2026-03-11 16:18:52
R W Run
13.17 KB
2026-03-11 16:18:52
R W Run
33.83 KB
2026-03-11 16:18:51
R W Run
42.63 KB
2026-03-11 16:18:51
R W Run
55.71 KB
2026-03-11 16:18:52
R W Run
12.53 KB
2026-03-11 16:18:51
R W Run
2.55 KB
2026-03-11 16:18:52
R W Run
28.92 KB
2026-03-11 16:18:52
R W Run
539 By
2026-03-11 16:18:51
R W Run
367 By
2026-03-11 16:18:52
R W Run
42.65 KB
2026-03-11 16:18:51
R W Run
401 By
2026-03-11 16:18:51
R W Run
6.61 KB
2026-03-11 16:18:51
R W Run
664 By
2026-03-11 16:18:52
R W Run
20.63 KB
2026-03-11 16:18:51
R W Run
2.18 KB
2026-03-11 16:18:52
R W Run
453 By
2026-03-11 16:18:52
R W Run
457 By
2026-03-11 16:18:51
R W Run
36.83 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
8.28 KB
2026-03-11 16:18:51
R W Run
13.89 KB
2026-03-11 16:18:51
R W Run
11.76 KB
2026-03-11 16:18:51
R W Run
2.65 KB
2026-03-11 16:18:51
R W Run
7.43 KB
2026-03-11 16:18:51
R W Run
17.46 KB
2026-03-11 16:18:51
R W Run
5.14 KB
2026-03-11 16:18:52
R W Run
16.7 KB
2026-03-11 16:18:51
R W Run
8.28 KB
2026-03-11 16:18:52
R W Run
2.92 KB
2026-03-11 16:18:52
R W Run
1.32 KB
2026-03-11 16:18:51
R W Run
4.6 KB
2026-03-11 16:18:52
R W Run
11.62 KB
2026-03-11 16:18:52
R W Run
2.5 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
11.25 KB
2026-03-11 16:18:52
R W Run
5.32 KB
2026-03-11 16:18:51
R W Run
10.99 KB
2026-03-11 16:18:52
R W Run
68.32 KB
2026-03-11 16:18:51
R W Run
6.34 KB
2026-03-11 16:18:51
R W Run
5.49 KB
2026-03-11 16:18:51
R W Run
1.99 KB
2026-03-11 16:18:52
R W Run
7.02 KB
2026-03-11 16:18:51
R W Run
4.91 KB
2026-03-11 16:18:52
R W Run
16.86 KB
2026-03-11 16:18:51
R W Run
24.23 KB
2026-03-11 16:18:51
R W Run
3.97 KB
2026-03-11 16:18:51
R W Run
47.66 KB
2026-03-11 16:18:51
R W Run
9.22 KB
2026-03-11 16:18:51
R W Run
25.51 KB
2026-03-11 16:18:51
R W Run
198.38 KB
2026-03-11 16:18:52
R W Run
56.65 KB
2026-03-11 16:18:51
R W Run
10.46 KB
2026-03-11 16:18:51
R W Run
10.95 KB
2026-03-11 16:18:52
R W Run
29.26 KB
2026-03-11 16:18:51
R W Run
70.91 KB
2026-03-11 16:18:52
R W Run
35.3 KB
2026-03-11 16:18:52
R W Run
16.61 KB
2026-03-11 16:18:52
R W Run
2.57 KB
2026-03-11 16:18:52
R W Run
39.83 KB
2026-03-11 16:18:51
R W Run
70.64 KB
2026-03-11 16:18:51
R W Run
15.56 KB
2026-03-11 16:18:52
R W Run
7.33 KB
2026-03-11 16:18:52
R W Run
253 By
2026-03-11 16:18:51
R W Run
7.96 KB
2026-03-11 16:18:52
R W Run
3.23 KB
2026-03-11 16:18:52
R W Run
969 By
2026-03-11 16:18:52
R W Run
16.28 KB
2026-03-11 16:18:51
R W Run
7.22 KB
2026-03-11 16:18:51
R W Run
12.95 KB
2026-03-11 16:18:51
R W Run
6.53 KB
2026-03-11 16:18:51
R W Run
3.42 KB
2026-03-11 16:18:52
R W Run
5.84 KB
2026-03-11 16:18:51
R W Run
1.97 KB
2026-03-11 16:18:51
R W Run
4.3 KB
2026-03-11 16:18:52
R W Run
2.91 KB
2026-03-11 16:18:51
R W Run
16.46 KB
2026-03-11 16:18:52
R W Run
40.6 KB
2026-03-11 16:18:51
R W Run
20.22 KB
2026-03-11 16:18:51
R W Run
36.11 KB
2026-03-11 16:18:52
R W Run
17.01 KB
2026-03-11 16:18:51
R W Run
7.27 KB
2026-03-11 16:18:52
R W Run
6.62 KB
2026-03-11 16:18:52
R W Run
16.49 KB
2026-03-11 16:18:52
R W Run
1.79 KB
2026-03-11 16:18:52
R W Run
29.82 KB
2026-03-11 16:18:51
R W Run
6.67 KB
2026-03-11 16:18:52
R W Run
8.98 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:51
R W Run
12.01 KB
2026-03-11 16:18:51
R W Run
17.11 KB
2026-03-11 16:18:51
R W Run
6.74 KB
2026-03-11 16:18:52
R W Run
30.93 KB
2026-03-11 16:18:51
R W Run
4.99 KB
2026-03-11 16:18:51
R W Run
4.25 KB
2026-03-11 16:18:51
R W Run
24.72 KB
2026-03-11 16:18:51
R W Run
29.96 KB
2026-03-11 16:18:52
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
160 KB
2026-03-11 16:18:51
R W Run
6.72 KB
2026-03-11 16:18:52
R W Run
10.92 KB
2026-03-11 16:18:51
R W Run
4.77 KB
2026-03-11 16:18:51
R W Run
3.38 KB
2026-03-11 16:18:51
R W Run
11.18 KB
2026-03-11 16:18:51
R W Run
62.19 KB
2026-03-11 16:18:51
R W Run
2.46 KB
2026-03-11 16:18:51
R W Run
9.17 KB
2026-03-11 16:18:51
R W Run
32.15 KB
2026-03-11 16:18:51
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
7.15 KB
2026-03-11 16:18:51
R W Run
3.47 KB
2026-03-11 16:18:52
R W Run
1.87 KB
2026-03-11 16:18:52
R W Run
30.91 KB
2026-03-11 16:18:51
R W Run
7.29 KB
2026-03-11 16:18:52
R W Run
7.35 KB
2026-03-11 16:18:51
R W Run
12.54 KB
2026-03-11 16:18:51
R W Run
19.12 KB
2026-03-11 16:18:51
R W Run
18.12 KB
2026-03-11 16:18:52
R W Run
39.99 KB
2026-03-11 16:18:52
R W Run
5.17 KB
2026-03-11 16:18:52
R W Run
979 By
2026-03-11 16:18:51
R W Run
18.44 KB
2026-03-11 16:18:52
R W Run
10.24 KB
2026-03-11 16:18:51
R W Run
1.77 KB
2026-03-11 16:18:52
R W Run
34.9 KB
2026-03-11 16:18:51
R W Run
7.19 KB
2026-03-11 16:18:52
R W Run
160.5 KB
2026-03-11 16:18:51
R W Run
64.27 KB
2026-03-11 16:18:51
R W Run
27.95 KB
2026-03-11 16:18:51
R W Run
4.69 KB
2026-03-11 16:18:51
R W Run
2.94 KB
2026-03-11 16:18:51
R W Run
43.13 KB
2026-03-11 16:18:52
R W Run
2.25 KB
2026-03-11 16:18:52
R W Run
22.5 KB
2026-03-11 16:18:51
R W Run
13.01 KB
2026-03-11 16:18:52
R W Run
3.27 KB
2026-03-11 16:18:51
R W Run
18 KB
2026-03-11 16:18:51
R W Run
210.4 KB
2026-03-11 16:18:52
R W Run
25.86 KB
2026-03-11 16:18:52
R W Run
115.85 KB
2026-03-11 16:18:51
R W Run
373 By
2026-03-11 16:18:52
R W Run
343 By
2026-03-11 16:18:52
R W Run
338 By
2026-03-11 16:18:51
R W Run
100.73 KB
2026-03-11 16:18:52
R W Run
130.93 KB
2026-03-11 16:18:51
R W Run
19.1 KB
2026-03-11 16:18:51
R W Run
17.41 KB
2026-03-11 16:18:52
R W Run
41.98 KB
2026-03-11 16:18:52
R W Run
400 By
2026-03-11 16:18:52
R W Run
11.1 KB
2026-03-11 16:18:52
R W Run
37.02 KB
2026-03-11 16:18:51
R W Run
2.24 KB
2026-03-11 16:18:51
R W Run
188.13 KB
2026-03-11 16:18:51
R W Run
338 By
2026-03-11 16:18:51
R W Run
38 KB
2026-03-11 16:18:51
R W Run
4.02 KB
2026-03-11 16:18:52
R W Run
5.38 KB
2026-03-11 16:18:51
R W Run
3.05 KB
2026-03-11 16:18:52
R W Run
2.61 KB
2026-03-11 16:18:51
R W Run
1.16 KB
2026-03-11 16:18:52
R W Run
4.04 KB
2026-03-11 16:18:51
R W Run
3.71 KB
2026-03-11 16:18:51
R W Run
24.6 KB
2026-03-11 16:18:51
R W Run
9.56 KB
2026-03-11 16:18:51
R W Run
346.43 KB
2026-03-11 16:18:52
R W Run
281.84 KB
2026-03-11 16:18:52
R W Run
14.95 KB
2026-03-11 16:18:51
R W Run
8.44 KB
2026-03-11 16:18:52
R W Run
168.95 KB
2026-03-11 16:18:52
R W Run
20.71 KB
2026-03-11 16:18:52
R W Run
25.27 KB
2026-03-11 16:18:51
R W Run
5.72 KB
2026-03-11 16:18:51
R W Run
4.63 KB
2026-03-11 16:18:52
R W Run
81.73 KB
2026-03-11 16:18:51
R W Run
67.18 KB
2026-03-11 16:18:51
R W Run
156.36 KB
2026-03-11 16:18:52
R W Run
55.19 KB
2026-03-11 16:18:51
R W Run
162 By
2026-03-11 16:18:51
R W Run
61.72 KB
2026-03-11 16:18:51
R W Run
216.06 KB
2026-03-11 16:18:52
R W Run
65.09 KB
2026-03-11 16:18:51
R W Run
25.24 KB
2026-03-11 16:18:52
R W Run
4.81 KB
2026-03-11 16:18:51
R W Run
6.48 KB
2026-03-11 16:18:52
R W Run
21.25 KB
2026-03-11 16:18:51
R W Run
2.79 KB
2026-03-11 16:18:52
R W Run
89.69 KB
2026-03-11 16:18:52
R W Run
19.42 KB
2026-03-11 16:18:52
R W Run
3.69 KB
2026-03-11 16:18:52
R W Run
4.11 KB
2026-03-11 16:18:51
R W Run
40.74 KB
2026-03-11 16:18:51
R W Run
25.38 KB
2026-03-11 16:18:51
R W Run
43.31 KB
2026-03-11 16:18:52
R W Run
102.57 KB
2026-03-11 16:18:52
R W Run
6.18 KB
2026-03-11 16:18:51
R W Run
124.47 KB
2026-03-11 16:18:52
R W Run
35.65 KB
2026-03-11 16:18:52
R W Run
6.94 KB
2026-03-11 16:18:52
R W Run
67.04 KB
2026-03-11 16:18:52
R W Run
10.62 KB
2026-03-11 16:18:51
R W Run
289.35 KB
2026-03-11 16:18:52
R W Run
36.23 KB
2026-03-11 16:18:51
R W Run
200 By
2026-03-11 16:18:52
R W Run
200 By
2026-03-11 16:18:52
R W Run
98.29 KB
2026-03-11 16:18:52
R W Run
30.02 KB
2026-03-11 16:18:52
R W Run
19.03 KB
2026-03-11 16:18:52
R W Run
5.06 KB
2026-03-11 16:18:52
R W Run
255 By
2026-03-11 16:18:51
R W Run
22.66 KB
2026-03-11 16:18:52
R W Run
154.63 KB
2026-03-11 16:18:51
R W Run
9.68 KB
2026-03-11 16:18:51
R W Run
258 By
2026-03-11 16:18:51
R W Run
23.49 KB
2026-03-11 16:18:51
R W Run
3.16 KB
2026-03-11 16:18:51
R W Run
8.4 KB
2026-03-11 16:18:52
R W Run
441 By
2026-03-11 16:18:51
R W Run
7.39 KB
2026-03-11 16:18:51
R W Run
173 KB
2026-03-11 16:18:52
R W Run
544 By
2026-03-11 16:18:52
R W Run
4.17 KB
2026-03-11 16:18:51
R W Run
35.97 KB
2026-03-11 16:18:52
R W Run
1.69 KB
2026-03-11 16:18:51
R W Run
2.84 KB
2026-03-11 16:18:52
R W Run
6.09 KB
2026-03-11 16:18:51
R W Run
8.71 KB
2026-03-11 16:18:51
R W Run
131.84 KB
2026-03-11 16:18:51
R W Run
37.45 KB
2026-03-11 16:18:51
R W Run
173.89 KB
2026-03-11 16:18:51
R W Run
7.09 KB
2026-03-11 16:18:51
R W Run
6.41 KB
2026-03-11 16:18:51
R W Run
1.08 KB
2026-03-11 16:18:51
R W Run
69.46 KB
2026-03-11 16:18:52
R W Run
445 By
2026-03-11 16:18:51
R W Run
799 By
2026-03-11 16:18:52
R W Run
error_log
📄class-wp-hook.php
1<?php
2/**
3 * Plugin API: WP_Hook class
4 *
5 * @package WordPress
6 * @subpackage Plugin
7 * @since 4.7.0
8 */
9
10/**
11 * Core class used to implement action and filter hook functionality.
12 *
13 * @since 4.7.0
14 *
15 * @see Iterator
16 * @see ArrayAccess
17 */
18#[AllowDynamicProperties]
19final class WP_Hook implements Iterator, ArrayAccess {
20
21 /**
22 * Hook callbacks.
23 *
24 * @since 4.7.0
25 * @var array
26 */
27 public $callbacks = array();
28
29 /**
30 * Priorities list.
31 *
32 * @since 6.4.0
33 * @var array
34 */
35 protected $priorities = array();
36
37 /**
38 * The priority keys of actively running iterations of a hook.
39 *
40 * @since 4.7.0
41 * @var array
42 */
43 private $iterations = array();
44
45 /**
46 * The current priority of actively running iterations of a hook.
47 *
48 * @since 4.7.0
49 * @var array
50 */
51 private $current_priority = array();
52
53 /**
54 * Number of levels this hook can be recursively called.
55 *
56 * @since 4.7.0
57 * @var int
58 */
59 private $nesting_level = 0;
60
61 /**
62 * Flag for if we're currently doing an action, rather than a filter.
63 *
64 * @since 4.7.0
65 * @var bool
66 */
67 private $doing_action = false;
68
69 /**
70 * Adds a callback function to a filter hook.
71 *
72 * @since 4.7.0
73 *
74 * @param string $hook_name The name of the filter to add the callback to.
75 * @param callable $callback The callback to be run when the filter is applied.
76 * @param int $priority The order in which the functions associated with a particular filter
77 * are executed. Lower numbers correspond with earlier execution,
78 * and functions with the same priority are executed in the order
79 * in which they were added to the filter.
80 * @param int $accepted_args The number of arguments the function accepts.
81 */
82 public function add_filter( $hook_name, $callback, $priority, $accepted_args ) {
83 if ( null === $priority ) {
84 $priority = 0;
85 }
86
87 $idx = _wp_filter_build_unique_id( $hook_name, $callback, $priority );
88
89 $priority_existed = isset( $this->callbacks[ $priority ] );
90
91 $this->callbacks[ $priority ][ $idx ] = array(
92 'function' => $callback,
93 'accepted_args' => (int) $accepted_args,
94 );
95
96 // If we're adding a new priority to the list, put them back in sorted order.
97 if ( ! $priority_existed && count( $this->callbacks ) > 1 ) {
98 ksort( $this->callbacks, SORT_NUMERIC );
99 }
100
101 $this->priorities = array_keys( $this->callbacks );
102
103 if ( $this->nesting_level > 0 ) {
104 $this->resort_active_iterations( $priority, $priority_existed );
105 }
106 }
107
108 /**
109 * Handles resetting callback priority keys mid-iteration.
110 *
111 * @since 4.7.0
112 *
113 * @param false|int $new_priority Optional. The priority of the new filter being added. Default false,
114 * for no priority being added.
115 * @param bool $priority_existed Optional. Flag for whether the priority already existed before the new
116 * filter was added. Default false.
117 */
118 private function resort_active_iterations( $new_priority = false, $priority_existed = false ) {
119 $new_priorities = $this->priorities;
120
121 // If there are no remaining hooks, clear out all running iterations.
122 if ( ! $new_priorities ) {
123 foreach ( $this->iterations as $index => $iteration ) {
124 $this->iterations[ $index ] = $new_priorities;
125 }
126
127 return;
128 }
129
130 $min = min( $new_priorities );
131
132 foreach ( $this->iterations as $index => &$iteration ) {
133 $current = current( $iteration );
134
135 // If we're already at the end of this iteration, just leave the array pointer where it is.
136 if ( false === $current ) {
137 continue;
138 }
139
140 $iteration = $new_priorities;
141
142 if ( $current < $min ) {
143 array_unshift( $iteration, $current );
144 continue;
145 }
146
147 while ( current( $iteration ) < $current ) {
148 if ( false === next( $iteration ) ) {
149 break;
150 }
151 }
152
153 // If we have a new priority that didn't exist, but ::apply_filters() or ::do_action() thinks it's the current priority...
154 if ( $new_priority === $this->current_priority[ $index ] && ! $priority_existed ) {
155 /*
156 * ...and the new priority is the same as what $this->iterations thinks is the previous
157 * priority, we need to move back to it.
158 */
159
160 if ( false === current( $iteration ) ) {
161 // If we've already moved off the end of the array, go back to the last element.
162 $prev = end( $iteration );
163 } else {
164 // Otherwise, just go back to the previous element.
165 $prev = prev( $iteration );
166 }
167
168 if ( false === $prev ) {
169 // Start of the array. Reset, and go about our day.
170 reset( $iteration );
171 } elseif ( $new_priority !== $prev ) {
172 // Previous wasn't the same. Move forward again.
173 next( $iteration );
174 }
175 }
176 }
177
178 unset( $iteration );
179 }
180
181 /**
182 * Removes a callback function from a filter hook.
183 *
184 * @since 4.7.0
185 *
186 * @param string $hook_name The filter hook to which the function to be removed is hooked.
187 * @param callable|string|array $callback The callback to be removed from running when the filter is applied.
188 * This method can be called unconditionally to speculatively remove
189 * a callback that may or may not exist.
190 * @param int $priority The exact priority used when adding the original filter callback.
191 * @return bool Whether the callback existed before it was removed.
192 */
193 public function remove_filter( $hook_name, $callback, $priority ) {
194 if ( null === $priority ) {
195 $priority = 0;
196 }
197
198 $function_key = _wp_filter_build_unique_id( $hook_name, $callback, $priority );
199
200 $exists = isset( $function_key, $this->callbacks[ $priority ][ $function_key ] );
201
202 if ( $exists ) {
203 unset( $this->callbacks[ $priority ][ $function_key ] );
204
205 if ( ! $this->callbacks[ $priority ] ) {
206 unset( $this->callbacks[ $priority ] );
207
208 $this->priorities = array_keys( $this->callbacks );
209
210 if ( $this->nesting_level > 0 ) {
211 $this->resort_active_iterations();
212 }
213 }
214 }
215
216 return $exists;
217 }
218
219 /**
220 * Checks if a specific callback has been registered for this hook.
221 *
222 * When using the `$callback` argument, this function may return a non-boolean value
223 * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value.
224 *
225 * @since 4.7.0
226 * @since 6.9.0 Added the `$priority` parameter.
227 *
228 * @param string $hook_name Optional. The name of the filter hook. Default empty.
229 * @param callable|string|array|false $callback Optional. The callback to check for.
230 * This method can be called unconditionally to speculatively check
231 * a callback that may or may not exist. Default false.
232 * @param int|false $priority Optional. The specific priority at which to check for the callback.
233 * Default false.
234 * @return bool|int If `$callback` is omitted, returns boolean for whether the hook has
235 * anything registered. When checking a specific function, the priority
236 * of that hook is returned, or false if the function is not attached.
237 * If `$callback` and `$priority` are both provided, a boolean is returned
238 * for whether the specific function is registered at that priority.
239 */
240 public function has_filter( $hook_name = '', $callback = false, $priority = false ) {
241 if ( false === $callback ) {
242 return $this->has_filters();
243 }
244
245 $function_key = _wp_filter_build_unique_id( $hook_name, $callback, false );
246
247 if ( ! $function_key ) {
248 return false;
249 }
250
251 if ( is_int( $priority ) ) {
252 return isset( $this->callbacks[ $priority ][ $function_key ] );
253 }
254
255 foreach ( $this->callbacks as $callback_priority => $callbacks ) {
256 if ( isset( $callbacks[ $function_key ] ) ) {
257 return $callback_priority;
258 }
259 }
260
261 return false;
262 }
263
264 /**
265 * Checks if any callbacks have been registered for this hook.
266 *
267 * @since 4.7.0
268 *
269 * @return bool True if callbacks have been registered for the current hook, otherwise false.
270 */
271 public function has_filters() {
272 foreach ( $this->callbacks as $callbacks ) {
273 if ( $callbacks ) {
274 return true;
275 }
276 }
277
278 return false;
279 }
280
281 /**
282 * Removes all callbacks from the current filter.
283 *
284 * @since 4.7.0
285 *
286 * @param int|false $priority Optional. The priority number to remove. Default false.
287 */
288 public function remove_all_filters( $priority = false ) {
289 if ( ! $this->callbacks ) {
290 return;
291 }
292
293 if ( false === $priority ) {
294 $this->callbacks = array();
295 $this->priorities = array();
296 } elseif ( isset( $this->callbacks[ $priority ] ) ) {
297 unset( $this->callbacks[ $priority ] );
298 $this->priorities = array_keys( $this->callbacks );
299 }
300
301 if ( $this->nesting_level > 0 ) {
302 $this->resort_active_iterations();
303 }
304 }
305
306 /**
307 * Calls the callback functions that have been added to a filter hook.
308 *
309 * @since 4.7.0
310 *
311 * @param mixed $value The value to filter.
312 * @param array $args Additional parameters to pass to the callback functions.
313 * This array is expected to include $value at index 0.
314 * @return mixed The filtered value after all hooked functions are applied to it.
315 */
316 public function apply_filters( $value, $args ) {
317 if ( ! $this->callbacks ) {
318 return $value;
319 }
320
321 $nesting_level = $this->nesting_level++;
322
323 $this->iterations[ $nesting_level ] = $this->priorities;
324
325 $num_args = count( $args );
326
327 do {
328 $this->current_priority[ $nesting_level ] = current( $this->iterations[ $nesting_level ] );
329
330 $priority = $this->current_priority[ $nesting_level ];
331
332 foreach ( $this->callbacks[ $priority ] as $the_ ) {
333 if ( ! $this->doing_action ) {
334 $args[0] = $value;
335 }
336
337 // Avoid the array_slice() if possible.
338 if ( 0 === $the_['accepted_args'] ) {
339 $value = call_user_func( $the_['function'] );
340 } elseif ( $the_['accepted_args'] >= $num_args ) {
341 $value = call_user_func_array( $the_['function'], $args );
342 } else {
343 $value = call_user_func_array( $the_['function'], array_slice( $args, 0, $the_['accepted_args'] ) );
344 }
345 }
346 } while ( false !== next( $this->iterations[ $nesting_level ] ) );
347
348 unset( $this->iterations[ $nesting_level ] );
349 unset( $this->current_priority[ $nesting_level ] );
350
351 --$this->nesting_level;
352
353 return $value;
354 }
355
356 /**
357 * Calls the callback functions that have been added to an action hook.
358 *
359 * @since 4.7.0
360 *
361 * @param array $args Parameters to pass to the callback functions.
362 */
363 public function do_action( $args ) {
364 $this->doing_action = true;
365 $this->apply_filters( '', $args );
366
367 // If there are recursive calls to the current action, we haven't finished it until we get to the last one.
368 if ( ! $this->nesting_level ) {
369 $this->doing_action = false;
370 }
371 }
372
373 /**
374 * Processes the functions hooked into the 'all' hook.
375 *
376 * @since 4.7.0
377 *
378 * @param array $args Arguments to pass to the hook callbacks. Passed by reference.
379 */
380 public function do_all_hook( &$args ) {
381 $nesting_level = $this->nesting_level++;
382 $this->iterations[ $nesting_level ] = $this->priorities;
383
384 do {
385 $priority = current( $this->iterations[ $nesting_level ] );
386
387 foreach ( $this->callbacks[ $priority ] as $the_ ) {
388 call_user_func_array( $the_['function'], $args );
389 }
390 } while ( false !== next( $this->iterations[ $nesting_level ] ) );
391
392 unset( $this->iterations[ $nesting_level ] );
393 --$this->nesting_level;
394 }
395
396 /**
397 * Return the current priority level of the currently running iteration of the hook.
398 *
399 * @since 4.7.0
400 *
401 * @return int|false If the hook is running, return the current priority level.
402 * If it isn't running, return false.
403 */
404 public function current_priority() {
405 if ( false === current( $this->iterations ) ) {
406 return false;
407 }
408
409 return current( current( $this->iterations ) );
410 }
411
412 /**
413 * Normalizes filters set up before WordPress has initialized to WP_Hook objects.
414 *
415 * The `$filters` parameter should be an array keyed by hook name, with values
416 * containing either:
417 *
418 * - A `WP_Hook` instance
419 * - An array of callbacks keyed by their priorities
420 *
421 * Examples:
422 *
423 * $filters = array(
424 * 'wp_fatal_error_handler_enabled' => array(
425 * 10 => array(
426 * array(
427 * 'accepted_args' => 0,
428 * 'function' => function() {
429 * return false;
430 * },
431 * ),
432 * ),
433 * ),
434 * );
435 *
436 * @since 4.7.0
437 *
438 * @param array $filters Filters to normalize. See documentation above for details.
439 * @return WP_Hook[] Array of normalized filters.
440 */
441 public static function build_preinitialized_hooks( $filters ) {
442 /** @var WP_Hook[] $normalized */
443 $normalized = array();
444
445 foreach ( $filters as $hook_name => $callback_groups ) {
446 if ( $callback_groups instanceof WP_Hook ) {
447 $normalized[ $hook_name ] = $callback_groups;
448 continue;
449 }
450
451 $hook = new WP_Hook();
452
453 // Loop through callback groups.
454 foreach ( $callback_groups as $priority => $callbacks ) {
455
456 // Loop through callbacks.
457 foreach ( $callbacks as $cb ) {
458 $hook->add_filter( $hook_name, $cb['function'], $priority, $cb['accepted_args'] );
459 }
460 }
461
462 $normalized[ $hook_name ] = $hook;
463 }
464
465 return $normalized;
466 }
467
468 /**
469 * Determines whether an offset value exists.
470 *
471 * @since 4.7.0
472 *
473 * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php
474 *
475 * @param mixed $offset An offset to check for.
476 * @return bool True if the offset exists, false otherwise.
477 */
478 #[ReturnTypeWillChange]
479 public function offsetExists( $offset ) {
480 return isset( $this->callbacks[ $offset ] );
481 }
482
483 /**
484 * Retrieves a value at a specified offset.
485 *
486 * @since 4.7.0
487 *
488 * @link https://www.php.net/manual/en/arrayaccess.offsetget.php
489 *
490 * @param mixed $offset The offset to retrieve.
491 * @return mixed If set, the value at the specified offset, null otherwise.
492 */
493 #[ReturnTypeWillChange]
494 public function offsetGet( $offset ) {
495 return isset( $this->callbacks[ $offset ] ) ? $this->callbacks[ $offset ] : null;
496 }
497
498 /**
499 * Sets a value at a specified offset.
500 *
501 * @since 4.7.0
502 *
503 * @link https://www.php.net/manual/en/arrayaccess.offsetset.php
504 *
505 * @param mixed $offset The offset to assign the value to.
506 * @param mixed $value The value to set.
507 */
508 #[ReturnTypeWillChange]
509 public function offsetSet( $offset, $value ) {
510 if ( is_null( $offset ) ) {
511 $this->callbacks[] = $value;
512 } else {
513 $this->callbacks[ $offset ] = $value;
514 }
515
516 $this->priorities = array_keys( $this->callbacks );
517 }
518
519 /**
520 * Unsets a specified offset.
521 *
522 * @since 4.7.0
523 *
524 * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php
525 *
526 * @param mixed $offset The offset to unset.
527 */
528 #[ReturnTypeWillChange]
529 public function offsetUnset( $offset ) {
530 unset( $this->callbacks[ $offset ] );
531 $this->priorities = array_keys( $this->callbacks );
532 }
533
534 /**
535 * Returns the current element.
536 *
537 * @since 4.7.0
538 *
539 * @link https://www.php.net/manual/en/iterator.current.php
540 *
541 * @return array Of callbacks at current priority.
542 */
543 #[ReturnTypeWillChange]
544 public function current() {
545 return current( $this->callbacks );
546 }
547
548 /**
549 * Moves forward to the next element.
550 *
551 * @since 4.7.0
552 *
553 * @link https://www.php.net/manual/en/iterator.next.php
554 *
555 * @return array Of callbacks at next priority.
556 */
557 #[ReturnTypeWillChange]
558 public function next() {
559 return next( $this->callbacks );
560 }
561
562 /**
563 * Returns the key of the current element.
564 *
565 * @since 4.7.0
566 *
567 * @link https://www.php.net/manual/en/iterator.key.php
568 *
569 * @return mixed Returns current priority on success, or NULL on failure
570 */
571 #[ReturnTypeWillChange]
572 public function key() {
573 return key( $this->callbacks );
574 }
575
576 /**
577 * Checks if current position is valid.
578 *
579 * @since 4.7.0
580 *
581 * @link https://www.php.net/manual/en/iterator.valid.php
582 *
583 * @return bool Whether the current position is valid.
584 */
585 #[ReturnTypeWillChange]
586 public function valid() {
587 return key( $this->callbacks ) !== null;
588 }
589
590 /**
591 * Rewinds the Iterator to the first element.
592 *
593 * @since 4.7.0
594 *
595 * @link https://www.php.net/manual/en/iterator.rewind.php
596 */
597 #[ReturnTypeWillChange]
598 public function rewind() {
599 reset( $this->callbacks );
600 }
601}
602