Issues (2010)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

wp-includes/plugin.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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://secure.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
12
 * type are valid.
13
 *
14
 * Also see the {@link https://codex.wordpress.org/Plugin_API 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
global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
26
27
if ( ! isset( $wp_filter ) )
28
	$wp_filter = array();
29
30
if ( ! isset( $wp_actions ) )
31
	$wp_actions = array();
32
33
if ( ! isset( $merged_filters ) )
34
	$merged_filters = array();
35
36
if ( ! isset( $wp_current_filter ) )
37
	$wp_current_filter = array();
38
39
/**
40
 * Hook a function or method to a specific filter action.
41
 *
42
 * WordPress offers filter hooks to allow plugins to modify
43
 * various types of internal data at runtime.
44
 *
45
 * A plugin can modify data by binding a callback to a filter hook. When the filter
46
 * is later applied, each bound callback is run in order of priority, and given
47
 * the opportunity to modify a value by returning a new value.
48
 *
49
 * The following example shows how a callback function is bound to a filter hook.
50
 *
51
 * Note that `$example` is passed to the callback, (maybe) modified, then returned:
52
 *
53
 *     function example_callback( $example ) {
54
 *         // Maybe modify $example in some way.
55
 *         return $example;
56
 *     }
57
 *     add_filter( 'example_filter', 'example_callback' );
58
 *
59
 * Bound callbacks can accept from none to the total number of arguments passed as parameters
60
 * in the corresponding apply_filters() call.
61
 *
62
 * In other words, if an apply_filters() call passes four total arguments, callbacks bound to
63
 * it can accept none (the same as 1) of the arguments or up to four. The important part is that
64
 * the `$accepted_args` value must reflect the number of arguments the bound callback *actually*
65
 * opted to accept. If no arguments were accepted by the callback that is considered to be the
66
 * same as accepting 1 argument. For example:
67
 *
68
 *     // Filter call.
69
 *     $value = apply_filters( 'hook', $value, $arg2, $arg3 );
70
 *
71
 *     // Accepting zero/one arguments.
72
 *     function example_callback() {
73
 *         ...
74
 *         return 'some value';
75
 *     }
76
 *     add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1.
77
 *
78
 *     // Accepting two arguments (three possible).
79
 *     function example_callback( $value, $arg2 ) {
80
 *         ...
81
 *         return $maybe_modified_value;
82
 *     }
83
 *     add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2.
84
 *
85
 * *Note:* The function will return true whether or not the callback is valid.
86
 * It is up to you to take care. This is done for optimization purposes, so
87
 * everything is as quick as possible.
88
 *
89
 * @since 0.71
90
 *
91
 * @global array $wp_filter      A multidimensional array of all hooks and the callbacks hooked to them.
92
 * @global array $merged_filters Tracks the tags that need to be merged for later. If the hook is added,
93
 *                               it doesn't need to run through that process.
94
 *
95
 * @param string   $tag             The name of the filter to hook the $function_to_add callback to.
96
 * @param callable $function_to_add The callback to be run when the filter is applied.
97
 * @param int      $priority        Optional. Used to specify the order in which the functions
98
 *                                  associated with a particular action are executed. Default 10.
99
 *                                  Lower numbers correspond with earlier execution,
100
 *                                  and functions with the same priority are executed
101
 *                                  in the order in which they were added to the action.
102
 * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
103
 * @return true
104
 */
105
function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
106
	global $wp_filter, $merged_filters;
107
108
	$idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
109
	$wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
110
	unset( $merged_filters[ $tag ] );
111
	return true;
112
}
113
114
/**
115
 * Check if any filter has been registered for a hook.
116
 *
117
 * @since 2.5.0
118
 *
119
 * @global array $wp_filter Stores all of the filters.
120
 *
121
 * @param string        $tag               The name of the filter hook.
122
 * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
123
 * @return false|int If $function_to_check is omitted, returns boolean for whether the hook has
124
 *                   anything registered. When checking a specific function, the priority of that
125
 *                   hook is returned, or false if the function is not attached. When using the
126
 *                   $function_to_check argument, this function may return a non-boolean value
127
 *                   that evaluates to false (e.g.) 0, so use the === operator for testing the
128
 *                   return value.
129
 */
130
function has_filter($tag, $function_to_check = false) {
131
	// Don't reset the internal array pointer
132
	$wp_filter = $GLOBALS['wp_filter'];
133
134
	$has = ! empty( $wp_filter[ $tag ] );
135
136
	// Make sure at least one priority has a filter callback
137
	if ( $has ) {
138
		$exists = false;
139
		foreach ( $wp_filter[ $tag ] as $callbacks ) {
140
			if ( ! empty( $callbacks ) ) {
141
				$exists = true;
142
				break;
143
			}
144
		}
145
146
		if ( ! $exists ) {
147
			$has = false;
148
		}
149
	}
150
151
	if ( false === $function_to_check || false === $has )
152
		return $has;
153
154
	if ( !$idx = _wp_filter_build_unique_id($tag, $function_to_check, false) )
0 ignored issues
show
It seems like $function_to_check defined by parameter $function_to_check on line 130 can also be of type boolean; however, _wp_filter_build_unique_id() does only seem to accept callable, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
155
		return false;
156
157
	foreach ( (array) array_keys($wp_filter[$tag]) as $priority ) {
158
		if ( isset($wp_filter[$tag][$priority][$idx]) )
159
			return $priority;
160
	}
161
162
	return false;
163
}
164
165
/**
166
 * Call the functions added to a filter hook.
167
 *
168
 * The callback functions attached to filter hook $tag are invoked by calling
169
 * this function. This function can be used to create a new filter hook by
170
 * simply calling this function with the name of the new hook specified using
171
 * the $tag parameter.
172
 *
173
 * The function allows for additional arguments to be added and passed to hooks.
174
 *
175
 *     // Our filter callback function
176
 *     function example_callback( $string, $arg1, $arg2 ) {
177
 *         // (maybe) modify $string
178
 *         return $string;
179
 *     }
180
 *     add_filter( 'example_filter', 'example_callback', 10, 3 );
181
 *
182
 *     /*
183
 *      * Apply the filters by calling the 'example_callback' function we
184
 *      * "hooked" to 'example_filter' using the add_filter() function above.
185
 *      * - 'example_filter' is the filter hook $tag
186
 *      * - 'filter me' is the value being filtered
187
 *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
188
 *     $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 );
189
 *
190
 * @since 0.71
191
 *
192
 * @global array $wp_filter         Stores all of the filters.
193
 * @global array $merged_filters    Merges the filter hooks using this function.
194
 * @global array $wp_current_filter Stores the list of current filters with the current one last.
195
 *
196
 * @param string $tag     The name of the filter hook.
197
 * @param mixed  $value   The value on which the filters hooked to `$tag` are applied on.
198
 * @param mixed  $var,... Additional variables passed to the functions hooked to `$tag`.
0 ignored issues
show
There is no parameter named $var,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
199
 * @return mixed The filtered value after all hooked functions are applied to it.
200
 */
201
function apply_filters( $tag, $value ) {
202
	global $wp_filter, $merged_filters, $wp_current_filter;
203
204
	$args = array();
205
206
	// Do 'all' actions first.
207 View Code Duplication
	if ( isset($wp_filter['all']) ) {
208
		$wp_current_filter[] = $tag;
209
		$args = func_get_args();
210
		_wp_call_all_hook($args);
211
	}
212
213 View Code Duplication
	if ( !isset($wp_filter[$tag]) ) {
214
		if ( isset($wp_filter['all']) )
215
			array_pop($wp_current_filter);
216
		return $value;
217
	}
218
219
	if ( !isset($wp_filter['all']) )
220
		$wp_current_filter[] = $tag;
221
222
	// Sort.
223 View Code Duplication
	if ( !isset( $merged_filters[ $tag ] ) ) {
224
		ksort($wp_filter[$tag]);
225
		$merged_filters[ $tag ] = true;
226
	}
227
228
	reset( $wp_filter[ $tag ] );
229
230
	if ( empty($args) )
231
		$args = func_get_args();
232
233
	do {
234
		foreach ( (array) current($wp_filter[$tag]) as $the_ )
235
			if ( !is_null($the_['function']) ){
236
				$args[1] = $value;
237
				$value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
238
			}
239
240
	} while ( next($wp_filter[$tag]) !== false );
241
242
	array_pop( $wp_current_filter );
243
244
	return $value;
245
}
246
247
/**
248
 * Execute functions hooked on a specific filter hook, specifying arguments in an array.
249
 *
250
 * @since 3.0.0
251
 *
252
 * @see apply_filters() This function is identical, but the arguments passed to the
253
 * functions hooked to `$tag` are supplied using an array.
254
 *
255
 * @global array $wp_filter         Stores all of the filters
256
 * @global array $merged_filters    Merges the filter hooks using this function.
257
 * @global array $wp_current_filter Stores the list of current filters with the current one last
258
 *
259
 * @param string $tag  The name of the filter hook.
260
 * @param array  $args The arguments supplied to the functions hooked to $tag.
261
 * @return mixed The filtered value after all hooked functions are applied to it.
262
 */
263
function apply_filters_ref_array($tag, $args) {
264
	global $wp_filter, $merged_filters, $wp_current_filter;
265
266
	// Do 'all' actions first
267 View Code Duplication
	if ( isset($wp_filter['all']) ) {
268
		$wp_current_filter[] = $tag;
269
		$all_args = func_get_args();
270
		_wp_call_all_hook($all_args);
271
	}
272
273 View Code Duplication
	if ( !isset($wp_filter[$tag]) ) {
274
		if ( isset($wp_filter['all']) )
275
			array_pop($wp_current_filter);
276
		return $args[0];
277
	}
278
279
	if ( !isset($wp_filter['all']) )
280
		$wp_current_filter[] = $tag;
281
282
	// Sort
283 View Code Duplication
	if ( !isset( $merged_filters[ $tag ] ) ) {
284
		ksort($wp_filter[$tag]);
285
		$merged_filters[ $tag ] = true;
286
	}
287
288
	reset( $wp_filter[ $tag ] );
289
290 View Code Duplication
	do {
291
		foreach ( (array) current($wp_filter[$tag]) as $the_ )
292
			if ( !is_null($the_['function']) )
293
				$args[0] = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
294
295
	} while ( next($wp_filter[$tag]) !== false );
296
297
	array_pop( $wp_current_filter );
298
299
	return $args[0];
300
}
301
302
/**
303
 * Removes a function from a specified filter hook.
304
 *
305
 * This function removes a function attached to a specified filter hook. This
306
 * method can be used to remove default functions attached to a specific filter
307
 * hook and possibly replace them with a substitute.
308
 *
309
 * To remove a hook, the $function_to_remove and $priority arguments must match
310
 * when the hook was added. This goes for both filters and actions. No warning
311
 * will be given on removal failure.
312
 *
313
 * @since 1.2.0
314
 *
315
 * @global array $wp_filter         Stores all of the filters
316
 * @global array $merged_filters    Merges the filter hooks using this function.
317
 *
318
 * @param string   $tag                The filter hook to which the function to be removed is hooked.
319
 * @param callable $function_to_remove The name of the function which should be removed.
320
 * @param int      $priority           Optional. The priority of the function. Default 10.
321
 * @return bool    Whether the function existed before it was removed.
322
 */
323
function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
324
	$function_to_remove = _wp_filter_build_unique_id( $tag, $function_to_remove, $priority );
325
326
	$r = isset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] );
327
328
	if ( true === $r ) {
329
		unset( $GLOBALS['wp_filter'][ $tag ][ $priority ][ $function_to_remove ] );
330
		if ( empty( $GLOBALS['wp_filter'][ $tag ][ $priority ] ) ) {
331
			unset( $GLOBALS['wp_filter'][ $tag ][ $priority ] );
332
		}
333
		if ( empty( $GLOBALS['wp_filter'][ $tag ] ) ) {
334
			$GLOBALS['wp_filter'][ $tag ] = array();
335
		}
336
		unset( $GLOBALS['merged_filters'][ $tag ] );
337
	}
338
339
	return $r;
340
}
341
342
/**
343
 * Remove all of the hooks from a filter.
344
 *
345
 * @since 2.7.0
346
 *
347
 * @global array $wp_filter         Stores all of the filters
348
 * @global array $merged_filters    Merges the filter hooks using this function.
349
 *
350
 * @param string   $tag      The filter to remove hooks from.
351
 * @param int|bool $priority Optional. The priority number to remove. Default false.
352
 * @return true True when finished.
353
 */
354
function remove_all_filters( $tag, $priority = false ) {
355
	global $wp_filter, $merged_filters;
356
357
	if ( isset( $wp_filter[ $tag ]) ) {
358
		if ( false === $priority ) {
359
			$wp_filter[ $tag ] = array();
360
		} elseif ( isset( $wp_filter[ $tag ][ $priority ] ) ) {
361
			$wp_filter[ $tag ][ $priority ] = array();
362
		}
363
	}
364
365
	unset( $merged_filters[ $tag ] );
366
367
	return true;
368
}
369
370
/**
371
 * Retrieve the name of the current filter or action.
372
 *
373
 * @since 2.5.0
374
 *
375
 * @global array $wp_current_filter Stores the list of current filters with the current one last
376
 *
377
 * @return string Hook name of the current filter or action.
378
 */
379
function current_filter() {
380
	global $wp_current_filter;
381
	return end( $wp_current_filter );
382
}
383
384
/**
385
 * Retrieve the name of the current action.
386
 *
387
 * @since 3.9.0
388
 *
389
 * @return string Hook name of the current action.
390
 */
391
function current_action() {
392
	return current_filter();
393
}
394
395
/**
396
 * Retrieve the name of a filter currently being processed.
397
 *
398
 * The function current_filter() only returns the most recent filter or action
399
 * being executed. did_action() returns true once the action is initially
400
 * processed.
401
 *
402
 * This function allows detection for any filter currently being
403
 * executed (despite not being the most recent filter to fire, in the case of
404
 * hooks called from hook callbacks) to be verified.
405
 *
406
 * @since 3.9.0
407
 *
408
 * @see current_filter()
409
 * @see did_action()
410
 * @global array $wp_current_filter Current filter.
411
 *
412
 * @param null|string $filter Optional. Filter to check. Defaults to null, which
413
 *                            checks if any filter is currently being run.
414
 * @return bool Whether the filter is currently in the stack.
415
 */
416
function doing_filter( $filter = null ) {
417
	global $wp_current_filter;
418
419
	if ( null === $filter ) {
420
		return ! empty( $wp_current_filter );
421
	}
422
423
	return in_array( $filter, $wp_current_filter );
424
}
425
426
/**
427
 * Retrieve the name of an action currently being processed.
428
 *
429
 * @since 3.9.0
430
 *
431
 * @param string|null $action Optional. Action to check. Defaults to null, which checks
432
 *                            if any action is currently being run.
433
 * @return bool Whether the action is currently in the stack.
434
 */
435
function doing_action( $action = null ) {
436
	return doing_filter( $action );
437
}
438
439
/**
440
 * Hooks a function on to a specific action.
441
 *
442
 * Actions are the hooks that the WordPress core launches at specific points
443
 * during execution, or when specific events occur. Plugins can specify that
444
 * one or more of its PHP functions are executed at these points, using the
445
 * Action API.
446
 *
447
 * @since 1.2.0
448
 *
449
 * @param string   $tag             The name of the action to which the $function_to_add is hooked.
450
 * @param callable $function_to_add The name of the function you wish to be called.
451
 * @param int      $priority        Optional. Used to specify the order in which the functions
452
 *                                  associated with a particular action are executed. Default 10.
453
 *                                  Lower numbers correspond with earlier execution,
454
 *                                  and functions with the same priority are executed
455
 *                                  in the order in which they were added to the action.
456
 * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
457
 * @return true Will always return true.
458
 */
459
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
460
	return add_filter($tag, $function_to_add, $priority, $accepted_args);
461
}
462
463
/**
464
 * Execute functions hooked on a specific action hook.
465
 *
466
 * This function invokes all functions attached to action hook `$tag`. It is
467
 * possible to create new action hooks by simply calling this function,
468
 * specifying the name of the new hook using the `$tag` parameter.
469
 *
470
 * You can pass extra arguments to the hooks, much like you can with apply_filters().
471
 *
472
 * @since 1.2.0
473
 *
474
 * @global array $wp_filter         Stores all of the filters
475
 * @global array $wp_actions        Increments the amount of times action was triggered.
476
 * @global array $merged_filters    Merges the filter hooks using this function.
477
 * @global array $wp_current_filter Stores the list of current filters with the current one last
478
 *
479
 * @param string $tag     The name of the action to be executed.
480
 * @param mixed  $arg,... Optional. Additional arguments which are passed on to the
0 ignored issues
show
There is no parameter named $arg,.... Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
481
 *                        functions hooked to the action. Default empty.
482
 */
483
function do_action($tag, $arg = '') {
484
	global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
485
486 View Code Duplication
	if ( ! isset($wp_actions[$tag]) )
487
		$wp_actions[$tag] = 1;
488
	else
489
		++$wp_actions[$tag];
490
491
	// Do 'all' actions first
492 View Code Duplication
	if ( isset($wp_filter['all']) ) {
493
		$wp_current_filter[] = $tag;
494
		$all_args = func_get_args();
495
		_wp_call_all_hook($all_args);
496
	}
497
498
	if ( !isset($wp_filter[$tag]) ) {
499
		if ( isset($wp_filter['all']) )
500
			array_pop($wp_current_filter);
501
		return;
502
	}
503
504
	if ( !isset($wp_filter['all']) )
505
		$wp_current_filter[] = $tag;
506
507
	$args = array();
508
	if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
509
		$args[] =& $arg[0];
510
	else
511
		$args[] = $arg;
512
	for ( $a = 2, $num = func_num_args(); $a < $num; $a++ )
513
		$args[] = func_get_arg($a);
514
515
	// Sort
516 View Code Duplication
	if ( !isset( $merged_filters[ $tag ] ) ) {
517
		ksort($wp_filter[$tag]);
518
		$merged_filters[ $tag ] = true;
519
	}
520
521
	reset( $wp_filter[ $tag ] );
522
523 View Code Duplication
	do {
524
		foreach ( (array) current($wp_filter[$tag]) as $the_ )
525
			if ( !is_null($the_['function']) )
526
				call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
527
528
	} while ( next($wp_filter[$tag]) !== false );
529
530
	array_pop($wp_current_filter);
531
}
532
533
/**
534
 * Retrieve the number of times an action is fired.
535
 *
536
 * @since 2.1.0
537
 *
538
 * @global array $wp_actions Increments the amount of times action was triggered.
539
 *
540
 * @param string $tag The name of the action hook.
541
 * @return int The number of times action hook $tag is fired.
542
 */
543
function did_action($tag) {
544
	global $wp_actions;
545
546
	if ( ! isset( $wp_actions[ $tag ] ) )
547
		return 0;
548
549
	return $wp_actions[$tag];
550
}
551
552
/**
553
 * Execute functions hooked on a specific action hook, specifying arguments in an array.
554
 *
555
 * @since 2.1.0
556
 *
557
 * @see do_action() This function is identical, but the arguments passed to the
558
 *                  functions hooked to $tag< are supplied using an array.
559
 * @global array $wp_filter         Stores all of the filters
560
 * @global array $wp_actions        Increments the amount of times action was triggered.
561
 * @global array $merged_filters    Merges the filter hooks using this function.
562
 * @global array $wp_current_filter Stores the list of current filters with the current one last
563
 *
564
 * @param string $tag  The name of the action to be executed.
565
 * @param array  $args The arguments supplied to the functions hooked to `$tag`.
566
 */
567
function do_action_ref_array($tag, $args) {
568
	global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
569
570 View Code Duplication
	if ( ! isset($wp_actions[$tag]) )
571
		$wp_actions[$tag] = 1;
572
	else
573
		++$wp_actions[$tag];
574
575
	// Do 'all' actions first
576 View Code Duplication
	if ( isset($wp_filter['all']) ) {
577
		$wp_current_filter[] = $tag;
578
		$all_args = func_get_args();
579
		_wp_call_all_hook($all_args);
580
	}
581
582
	if ( !isset($wp_filter[$tag]) ) {
583
		if ( isset($wp_filter['all']) )
584
			array_pop($wp_current_filter);
585
		return;
586
	}
587
588
	if ( !isset($wp_filter['all']) )
589
		$wp_current_filter[] = $tag;
590
591
	// Sort
592 View Code Duplication
	if ( !isset( $merged_filters[ $tag ] ) ) {
593
		ksort($wp_filter[$tag]);
594
		$merged_filters[ $tag ] = true;
595
	}
596
597
	reset( $wp_filter[ $tag ] );
598
599 View Code Duplication
	do {
600
		foreach ( (array) current($wp_filter[$tag]) as $the_ )
601
			if ( !is_null($the_['function']) )
602
				call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
603
604
	} while ( next($wp_filter[$tag]) !== false );
605
606
	array_pop($wp_current_filter);
607
}
608
609
/**
610
 * Check if any action has been registered for a hook.
611
 *
612
 * @since 2.5.0
613
 *
614
 * @see has_filter() has_action() is an alias of has_filter().
615
 *
616
 * @param string        $tag               The name of the action hook.
617
 * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
618
 * @return bool|int If $function_to_check is omitted, returns boolean for whether the hook has
619
 *                  anything registered. When checking a specific function, the priority of that
620
 *                  hook is returned, or false if the function is not attached. When using the
621
 *                  $function_to_check argument, this function may return a non-boolean value
622
 *                  that evaluates to false (e.g.) 0, so use the === operator for testing the
623
 *                  return value.
624
 */
625
function has_action($tag, $function_to_check = false) {
626
	return has_filter($tag, $function_to_check);
627
}
628
629
/**
630
 * Removes a function from a specified action hook.
631
 *
632
 * This function removes a function attached to a specified action hook. This
633
 * method can be used to remove default functions attached to a specific filter
634
 * hook and possibly replace them with a substitute.
635
 *
636
 * @since 1.2.0
637
 *
638
 * @param string   $tag                The action hook to which the function to be removed is hooked.
639
 * @param callable $function_to_remove The name of the function which should be removed.
640
 * @param int      $priority           Optional. The priority of the function. Default 10.
641
 * @return bool Whether the function is removed.
642
 */
643
function remove_action( $tag, $function_to_remove, $priority = 10 ) {
644
	return remove_filter( $tag, $function_to_remove, $priority );
645
}
646
647
/**
648
 * Remove all of the hooks from an action.
649
 *
650
 * @since 2.7.0
651
 *
652
 * @param string   $tag      The action to remove hooks from.
653
 * @param int|bool $priority The priority number to remove them from. Default false.
654
 * @return true True when finished.
655
 */
656
function remove_all_actions($tag, $priority = false) {
657
	return remove_all_filters($tag, $priority);
658
}
659
660
/**
661
 * Fires functions attached to a deprecated filter hook.
662
 *
663
 * When a filter hook is deprecated, the apply_filters() call is replaced with
664
 * apply_filters_deprecated(), which triggers a deprecation notice and then fires
665
 * the original filter hook.
666
 *
667
 * @since 4.6.0
668
 *
669
 * @see _deprecated_hook()
670
 *
671
 * @param string $tag         The name of the filter hook.
672
 * @param array  $args        Array of additional function arguments to be passed to apply_filters().
673
 * @param string $version     The version of WordPress that deprecated the hook.
674
 * @param string $replacement Optional. The hook that should have been used. Default false.
675
 * @param string $message     Optional. A message regarding the change. Default null.
676
 */
677
function apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
678
	if ( ! has_filter( $tag ) ) {
679
		return $args[0];
680
	}
681
682
	_deprecated_hook( $tag, $version, $replacement, $message );
0 ignored issues
show
It seems like $replacement defined by parameter $replacement on line 677 can also be of type false; however, _deprecated_hook() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
683
684
	return apply_filters_ref_array( $tag, $args );
685
}
686
687
/**
688
 * Fires functions attached to a deprecated action hook.
689
 *
690
 * When an action hook is deprecated, the do_action() call is replaced with
691
 * do_action_deprecated(), which triggers a deprecation notice and then fires
692
 * the original hook.
693
 *
694
 * @since 4.6.0
695
 *
696
 * @see _deprecated_hook()
697
 *
698
 * @param string $tag         The name of the action hook.
699
 * @param array  $args        Array of additional function arguments to be passed to do_action().
700
 * @param string $version     The version of WordPress that deprecated the hook.
701
 * @param string $replacement Optional. The hook that should have been used.
702
 * @param string $message     Optional. A message regarding the change.
703
 */
704
function do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
705
	if ( ! has_action( $tag ) ) {
706
		return;
707
	}
708
709
	_deprecated_hook( $tag, $version, $replacement, $message );
0 ignored issues
show
It seems like $replacement defined by parameter $replacement on line 704 can also be of type false; however, _deprecated_hook() does only seem to accept string|null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
710
711
	do_action_ref_array( $tag, $args );
712
}
713
714
//
715
// Functions for handling plugins.
716
//
717
718
/**
719
 * Gets the basename of a plugin.
720
 *
721
 * This method extracts the name of a plugin from its filename.
722
 *
723
 * @since 1.5.0
724
 *
725
 * @global array $wp_plugin_paths
726
 *
727
 * @param string $file The filename of plugin.
728
 * @return string The name of a plugin.
729
 */
730
function plugin_basename( $file ) {
731
	global $wp_plugin_paths;
732
733
	// $wp_plugin_paths contains normalized paths.
734
	$file = wp_normalize_path( $file );
735
736
	arsort( $wp_plugin_paths );
737
	foreach ( $wp_plugin_paths as $dir => $realdir ) {
738
		if ( strpos( $file, $realdir ) === 0 ) {
739
			$file = $dir . substr( $file, strlen( $realdir ) );
740
		}
741
	}
742
743
	$plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
744
	$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
745
746
	$file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#','',$file); // get relative path from plugins dir
747
	$file = trim($file, '/');
748
	return $file;
749
}
750
751
/**
752
 * Register a plugin's real path.
753
 *
754
 * This is used in plugin_basename() to resolve symlinked paths.
755
 *
756
 * @since 3.9.0
757
 *
758
 * @see wp_normalize_path()
759
 *
760
 * @global array $wp_plugin_paths
761
 *
762
 * @staticvar string $wp_plugin_path
763
 * @staticvar string $wpmu_plugin_path
764
 *
765
 * @param string $file Known path to the file.
766
 * @return bool Whether the path was able to be registered.
767
 */
768
function wp_register_plugin_realpath( $file ) {
769
	global $wp_plugin_paths;
770
771
	// Normalize, but store as static to avoid recalculation of a constant value
772
	static $wp_plugin_path = null, $wpmu_plugin_path = null;
773
	if ( ! isset( $wp_plugin_path ) ) {
774
		$wp_plugin_path   = wp_normalize_path( WP_PLUGIN_DIR   );
775
		$wpmu_plugin_path = wp_normalize_path( WPMU_PLUGIN_DIR );
776
	}
777
778
	$plugin_path = wp_normalize_path( dirname( $file ) );
779
	$plugin_realpath = wp_normalize_path( dirname( realpath( $file ) ) );
780
781
	if ( $plugin_path === $wp_plugin_path || $plugin_path === $wpmu_plugin_path ) {
782
		return false;
783
	}
784
785
	if ( $plugin_path !== $plugin_realpath ) {
786
		$wp_plugin_paths[ $plugin_path ] = $plugin_realpath;
787
	}
788
789
	return true;
790
}
791
792
/**
793
 * Get the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in.
794
 *
795
 * @since 2.8.0
796
 *
797
 * @param string $file The filename of the plugin (__FILE__).
798
 * @return string the filesystem path of the directory that contains the plugin.
799
 */
800
function plugin_dir_path( $file ) {
801
	return trailingslashit( dirname( $file ) );
802
}
803
804
/**
805
 * Get the URL directory path (with trailing slash) for the plugin __FILE__ passed in.
806
 *
807
 * @since 2.8.0
808
 *
809
 * @param string $file The filename of the plugin (__FILE__).
810
 * @return string the URL path of the directory that contains the plugin.
811
 */
812
function plugin_dir_url( $file ) {
813
	return trailingslashit( plugins_url( '', $file ) );
814
}
815
816
/**
817
 * Set the activation hook for a plugin.
818
 *
819
 * When a plugin is activated, the action 'activate_PLUGINNAME' hook is
820
 * called. In the name of this hook, PLUGINNAME is replaced with the name
821
 * of the plugin, including the optional subdirectory. For example, when the
822
 * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
823
 * the name of this hook will become 'activate_sampleplugin/sample.php'.
824
 *
825
 * When the plugin consists of only one file and is (as by default) located at
826
 * wp-content/plugins/sample.php the name of this hook will be
827
 * 'activate_sample.php'.
828
 *
829
 * @since 2.0.0
830
 *
831
 * @param string   $file     The filename of the plugin including the path.
832
 * @param callable $function The function hooked to the 'activate_PLUGIN' action.
833
 */
834
function register_activation_hook($file, $function) {
835
	$file = plugin_basename($file);
836
	add_action('activate_' . $file, $function);
837
}
838
839
/**
840
 * Set the deactivation hook for a plugin.
841
 *
842
 * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is
843
 * called. In the name of this hook, PLUGINNAME is replaced with the name
844
 * of the plugin, including the optional subdirectory. For example, when the
845
 * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
846
 * the name of this hook will become 'deactivate_sampleplugin/sample.php'.
847
 *
848
 * When the plugin consists of only one file and is (as by default) located at
849
 * wp-content/plugins/sample.php the name of this hook will be
850
 * 'deactivate_sample.php'.
851
 *
852
 * @since 2.0.0
853
 *
854
 * @param string   $file     The filename of the plugin including the path.
855
 * @param callable $function The function hooked to the 'deactivate_PLUGIN' action.
856
 */
857
function register_deactivation_hook($file, $function) {
858
	$file = plugin_basename($file);
859
	add_action('deactivate_' . $file, $function);
860
}
861
862
/**
863
 * Set the uninstallation hook for a plugin.
864
 *
865
 * Registers the uninstall hook that will be called when the user clicks on the
866
 * uninstall link that calls for the plugin to uninstall itself. The link won't
867
 * be active unless the plugin hooks into the action.
868
 *
869
 * The plugin should not run arbitrary code outside of functions, when
870
 * registering the uninstall hook. In order to run using the hook, the plugin
871
 * will have to be included, which means that any code laying outside of a
872
 * function will be run during the uninstall process. The plugin should not
873
 * hinder the uninstall process.
874
 *
875
 * If the plugin can not be written without running code within the plugin, then
876
 * the plugin should create a file named 'uninstall.php' in the base plugin
877
 * folder. This file will be called, if it exists, during the uninstall process
878
 * bypassing the uninstall hook. The plugin, when using the 'uninstall.php'
879
 * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before
880
 * executing.
881
 *
882
 * @since 2.7.0
883
 *
884
 * @param string   $file     Plugin file.
885
 * @param callable $callback The callback to run when the hook is called. Must be
886
 *                           a static method or function.
887
 */
888
function register_uninstall_hook( $file, $callback ) {
889
	if ( is_array( $callback ) && is_object( $callback[0] ) ) {
890
		_doing_it_wrong( __FUNCTION__, __( 'Only a static class method or function can be used in an uninstall hook.' ), '3.1.0' );
891
		return;
892
	}
893
894
	/*
895
	 * The option should not be autoloaded, because it is not needed in most
896
	 * cases. Emphasis should be put on using the 'uninstall.php' way of
897
	 * uninstalling the plugin.
898
	 */
899
	$uninstallable_plugins = (array) get_option('uninstall_plugins');
900
	$uninstallable_plugins[plugin_basename($file)] = $callback;
901
902
	update_option('uninstall_plugins', $uninstallable_plugins);
903
}
904
905
/**
906
 * Call the 'all' hook, which will process the functions hooked into it.
907
 *
908
 * The 'all' hook passes all of the arguments or parameters that were used for
909
 * the hook, which this function was called for.
910
 *
911
 * This function is used internally for apply_filters(), do_action(), and
912
 * do_action_ref_array() and is not meant to be used from outside those
913
 * functions. This function does not check for the existence of the all hook, so
914
 * it will fail unless the all hook exists prior to this function call.
915
 *
916
 * @since 2.5.0
917
 * @access private
918
 *
919
 * @global array $wp_filter  Stores all of the filters
920
 *
921
 * @param array $args The collected parameters from the hook that was called.
922
 */
923
function _wp_call_all_hook($args) {
924
	global $wp_filter;
925
926
	reset( $wp_filter['all'] );
927
	do {
928
		foreach ( (array) current($wp_filter['all']) as $the_ )
929
			if ( !is_null($the_['function']) )
930
				call_user_func_array($the_['function'], $args);
931
932
	} while ( next($wp_filter['all']) !== false );
933
}
934
935
/**
936
 * Build Unique ID for storage and retrieval.
937
 *
938
 * The old way to serialize the callback caused issues and this function is the
939
 * solution. It works by checking for objects and creating a new property in
940
 * the class to keep track of the object and new objects of the same class that
941
 * need to be added.
942
 *
943
 * It also allows for the removal of actions and filters for objects after they
944
 * change class properties. It is possible to include the property $wp_filter_id
945
 * in your class and set it to "null" or a number to bypass the workaround.
946
 * However this will prevent you from adding new classes and any new classes
947
 * will overwrite the previous hook by the same class.
948
 *
949
 * Functions and static method callbacks are just returned as strings and
950
 * shouldn't have any speed penalty.
951
 *
952
 * @link https://core.trac.wordpress.org/ticket/3875
953
 *
954
 * @since 2.2.3
955
 * @access private
956
 *
957
 * @global array $wp_filter Storage for all of the filters and actions.
958
 * @staticvar int $filter_id_count
959
 *
960
 * @param string   $tag      Used in counting how many hooks were applied
961
 * @param callable $function Used for creating unique id
962
 * @param int|bool $priority Used in counting how many hooks were applied. If === false
963
 *                           and $function is an object reference, we return the unique
964
 *                           id only if it already has one, false otherwise.
965
 * @return string|false Unique ID for usage as array key or false if $priority === false
966
 *                      and $function is an object reference, and it does not already have
967
 *                      a unique id.
968
 */
969
function _wp_filter_build_unique_id($tag, $function, $priority) {
970
	global $wp_filter;
971
	static $filter_id_count = 0;
972
973
	if ( is_string($function) )
974
		return $function;
975
976
	if ( is_object($function) ) {
977
		// Closures are currently implemented as objects
978
		$function = array( $function, '' );
979
	} else {
980
		$function = (array) $function;
981
	}
982
983
	if (is_object($function[0]) ) {
984
		// Object Class Calling
985
		if ( function_exists('spl_object_hash') ) {
986
			return spl_object_hash($function[0]) . $function[1];
987
		} else {
988
			$obj_idx = get_class($function[0]).$function[1];
989
			if ( !isset($function[0]->wp_filter_id) ) {
990
				if ( false === $priority )
991
					return false;
992
				$obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count;
993
				$function[0]->wp_filter_id = $filter_id_count;
994
				++$filter_id_count;
995
			} else {
996
				$obj_idx .= $function[0]->wp_filter_id;
997
			}
998
999
			return $obj_idx;
1000
		}
1001
	} elseif ( is_string( $function[0] ) ) {
1002
		// Static Calling
1003
		return $function[0] . '::' . $function[1];
1004
	}
1005
}
1006