Issues (4967)

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.

src/wp-includes/plugin.php (11 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
require( dirname( __FILE__ ) . '/class-wp-hook.php' );
26
27
/** @var WP_Hook[] $wp_filter */
28
global $wp_filter, $wp_actions, $wp_current_filter;
29
30
if ( $wp_filter ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $wp_filter of type WP_Hook[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
31
	$wp_filter = WP_Hook::build_preinitialized_hooks( $wp_filter );
32
} else {
33
	$wp_filter = array();
34
}
35
36
if ( ! isset( $wp_actions ) )
37
	$wp_actions = array();
38
39
if ( ! isset( $wp_current_filter ) )
40
	$wp_current_filter = array();
41
42
/**
43
 * Hook a function or method to a specific filter action.
44
 *
45
 * WordPress offers filter hooks to allow plugins to modify
46
 * various types of internal data at runtime.
47
 *
48
 * A plugin can modify data by binding a callback to a filter hook. When the filter
49
 * is later applied, each bound callback is run in order of priority, and given
50
 * the opportunity to modify a value by returning a new value.
51
 *
52
 * The following example shows how a callback function is bound to a filter hook.
53
 *
54
 * Note that `$example` is passed to the callback, (maybe) modified, then returned:
55
 *
56
 *     function example_callback( $example ) {
57
 *         // Maybe modify $example in some way.
58
 *         return $example;
59
 *     }
60
 *     add_filter( 'example_filter', 'example_callback' );
61
 *
62
 * Bound callbacks can accept from none to the total number of arguments passed as parameters
63
 * in the corresponding apply_filters() call.
64
 *
65
 * In other words, if an apply_filters() call passes four total arguments, callbacks bound to
66
 * it can accept none (the same as 1) of the arguments or up to four. The important part is that
67
 * the `$accepted_args` value must reflect the number of arguments the bound callback *actually*
68
 * opted to accept. If no arguments were accepted by the callback that is considered to be the
69
 * same as accepting 1 argument. For example:
70
 *
71
 *     // Filter call.
72
 *     $value = apply_filters( 'hook', $value, $arg2, $arg3 );
73
 *
74
 *     // Accepting zero/one arguments.
75
 *     function example_callback() {
76
 *         ...
77
 *         return 'some value';
78
 *     }
79
 *     add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1.
80
 *
81
 *     // Accepting two arguments (three possible).
82
 *     function example_callback( $value, $arg2 ) {
83
 *         ...
84
 *         return $maybe_modified_value;
85
 *     }
86
 *     add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2.
87
 *
88
 * *Note:* The function will return true whether or not the callback is valid.
89
 * It is up to you to take care. This is done for optimization purposes, so
90
 * everything is as quick as possible.
91
 *
92
 * @since 0.71
93
 *
94
 * @global array $wp_filter      A multidimensional array of all hooks and the callbacks hooked to them.
95
 *
96
 * @param string   $tag             The name of the filter to hook the $function_to_add callback to.
97
 * @param callable $function_to_add The callback to be run when the filter is applied.
98
 * @param int      $priority        Optional. Used to specify the order in which the functions
99
 *                                  associated with a particular action are executed. Default 10.
100
 *                                  Lower numbers correspond with earlier execution,
101
 *                                  and functions with the same priority are executed
102
 *                                  in the order in which they were added to the action.
103
 * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
104
 * @return true
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
105
 */
106
function add_filter( $tag, $function_to_add, $priority = 10, $accepted_args = 1 ) {
107
	global $wp_filter;
108
	if ( ! isset( $wp_filter[ $tag ] ) ) {
109
		$wp_filter[ $tag ] = new WP_Hook();
110
	}
111
	$wp_filter[ $tag ]->add_filter( $tag, $function_to_add, $priority, $accepted_args );
112
	return true;
113
}
114
115
/**
116
 * Check if any filter has been registered for a hook.
117
 *
118
 * @since 2.5.0
119
 *
120
 * @global array $wp_filter Stores all of the filters.
121
 *
122
 * @param string        $tag               The name of the filter hook.
123
 * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
124
 * @return false|int If $function_to_check is omitted, returns boolean for whether the hook has
125
 *                   anything registered. When checking a specific function, the priority of that
126
 *                   hook is returned, or false if the function is not attached. When using the
127
 *                   $function_to_check argument, this function may return a non-boolean value
128
 *                   that evaluates to false (e.g.) 0, so use the === operator for testing the
129
 *                   return value.
130
 */
131
function has_filter($tag, $function_to_check = false) {
132
	global $wp_filter;
133
134
	if ( ! isset( $wp_filter[ $tag ] ) ) {
135
		return false;
136
	}
137
138
	return $wp_filter[ $tag ]->has_filter( $tag, $function_to_check );
139
}
140
141
/**
142
 * Call the functions added to a filter hook.
143
 *
144
 * The callback functions attached to filter hook $tag are invoked by calling
145
 * this function. This function can be used to create a new filter hook by
146
 * simply calling this function with the name of the new hook specified using
147
 * the $tag parameter.
148
 *
149
 * The function allows for additional arguments to be added and passed to hooks.
150
 *
151
 *     // Our filter callback function
152
 *     function example_callback( $string, $arg1, $arg2 ) {
153
 *         // (maybe) modify $string
154
 *         return $string;
155
 *     }
156
 *     add_filter( 'example_filter', 'example_callback', 10, 3 );
157
 *
158
 *     /*
159
 *      * Apply the filters by calling the 'example_callback' function we
160
 *      * "hooked" to 'example_filter' using the add_filter() function above.
161
 *      * - 'example_filter' is the filter hook $tag
162
 *      * - 'filter me' is the value being filtered
163
 *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
164
 *     $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 );
165
 *
166
 * @since 0.71
167
 *
168
 * @global array $wp_filter         Stores all of the filters.
169
 * @global array $wp_current_filter Stores the list of current filters with the current one last.
170
 *
171
 * @param string $tag     The name of the filter hook.
172
 * @param mixed  $value   The value on which the filters hooked to `$tag` are applied on.
173
 * @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...
174
 * @return mixed The filtered value after all hooked functions are applied to it.
175
 */
176
function apply_filters( $tag, $value ) {
177
	global $wp_filter, $wp_current_filter;
178
179
	$args = array();
180
181
	// Do 'all' actions first.
182 View Code Duplication
	if ( isset($wp_filter['all']) ) {
183
		$wp_current_filter[] = $tag;
184
		$args = func_get_args();
185
		_wp_call_all_hook($args);
186
	}
187
188 View Code Duplication
	if ( !isset($wp_filter[$tag]) ) {
189
		if ( isset($wp_filter['all']) )
190
			array_pop($wp_current_filter);
191
		return $value;
192
	}
193
194
	if ( !isset($wp_filter['all']) )
195
		$wp_current_filter[] = $tag;
196
197
	if ( empty($args) )
198
		$args = func_get_args();
199
200
	// don't pass the tag name to WP_Hook
201
	array_shift( $args );
202
203
	$filtered = $wp_filter[ $tag ]->apply_filters( $value, $args );
204
205
	array_pop( $wp_current_filter );
206
207
	return $filtered;
208
}
209
210
/**
211
 * Execute functions hooked on a specific filter hook, specifying arguments in an array.
212
 *
213
 * @since 3.0.0
214
 *
215
 * @see apply_filters() This function is identical, but the arguments passed to the
216
 * functions hooked to `$tag` are supplied using an array.
217
 *
218
 * @global array $wp_filter         Stores all of the filters
219
 * @global array $wp_current_filter Stores the list of current filters with the current one last
220
 *
221
 * @param string $tag  The name of the filter hook.
222
 * @param array  $args The arguments supplied to the functions hooked to $tag.
223
 * @return mixed The filtered value after all hooked functions are applied to it.
224
 */
225
function apply_filters_ref_array($tag, $args) {
226
	global $wp_filter, $wp_current_filter;
227
228
	// Do 'all' actions first
229 View Code Duplication
	if ( isset($wp_filter['all']) ) {
230
		$wp_current_filter[] = $tag;
231
		$all_args = func_get_args();
232
		_wp_call_all_hook($all_args);
233
	}
234
235 View Code Duplication
	if ( !isset($wp_filter[$tag]) ) {
236
		if ( isset($wp_filter['all']) )
237
			array_pop($wp_current_filter);
238
		return $args[0];
239
	}
240
241
	if ( !isset($wp_filter['all']) )
242
		$wp_current_filter[] = $tag;
243
244
	$filtered = $wp_filter[ $tag ]->apply_filters( $args[0], $args );
245
246
	array_pop( $wp_current_filter );
247
248
	return $filtered;
249
}
250
251
/**
252
 * Removes a function from a specified filter hook.
253
 *
254
 * This function removes a function attached to a specified filter hook. This
255
 * method can be used to remove default functions attached to a specific filter
256
 * hook and possibly replace them with a substitute.
257
 *
258
 * To remove a hook, the $function_to_remove and $priority arguments must match
259
 * when the hook was added. This goes for both filters and actions. No warning
260
 * will be given on removal failure.
261
 *
262
 * @since 1.2.0
263
 *
264
 * @global array $wp_filter         Stores all of the filters
265
 *
266
 * @param string   $tag                The filter hook to which the function to be removed is hooked.
267
 * @param callable $function_to_remove The name of the function which should be removed.
268
 * @param int      $priority           Optional. The priority of the function. Default 10.
269
 * @return bool    Whether the function existed before it was removed.
270
 */
271
function remove_filter( $tag, $function_to_remove, $priority = 10 ) {
272
	global $wp_filter;
273
274
	$r = false;
275
	if ( isset( $wp_filter[ $tag ] ) ) {
276
		$r = $wp_filter[ $tag ]->remove_filter( $tag, $function_to_remove, $priority );
277
		if ( ! $wp_filter[ $tag ]->callbacks ) {
278
			unset( $wp_filter[ $tag ] );
279
		}
280
	}
281
282
	return $r;
283
}
284
285
/**
286
 * Remove all of the hooks from a filter.
287
 *
288
 * @since 2.7.0
289
 *
290
 * @global array $wp_filter  Stores all of the filters
291
 *
292
 * @param string   $tag      The filter to remove hooks from.
293
 * @param int|bool $priority Optional. The priority number to remove. Default false.
294
 * @return true True when finished.
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
295
 */
296
function remove_all_filters( $tag, $priority = false ) {
297
	global $wp_filter;
298
299
	if ( isset( $wp_filter[ $tag ]) ) {
300
		$wp_filter[ $tag ]->remove_all_filters( $priority );
301
		if ( ! $wp_filter[ $tag ]->has_filters() ) {
302
			unset( $wp_filter[ $tag ] );
303
		}
304
	}
305
306
	return true;
307
}
308
309
/**
310
 * Retrieve the name of the current filter or action.
311
 *
312
 * @since 2.5.0
313
 *
314
 * @global array $wp_current_filter Stores the list of current filters with the current one last
315
 *
316
 * @return string Hook name of the current filter or action.
317
 */
318
function current_filter() {
319
	global $wp_current_filter;
320
	return end( $wp_current_filter );
321
}
322
323
/**
324
 * Retrieve the name of the current action.
325
 *
326
 * @since 3.9.0
327
 *
328
 * @return string Hook name of the current action.
329
 */
330
function current_action() {
331
	return current_filter();
332
}
333
334
/**
335
 * Retrieve the name of a filter currently being processed.
336
 *
337
 * The function current_filter() only returns the most recent filter or action
338
 * being executed. did_action() returns true once the action is initially
339
 * processed.
340
 *
341
 * This function allows detection for any filter currently being
342
 * executed (despite not being the most recent filter to fire, in the case of
343
 * hooks called from hook callbacks) to be verified.
344
 *
345
 * @since 3.9.0
346
 *
347
 * @see current_filter()
348
 * @see did_action()
349
 * @global array $wp_current_filter Current filter.
350
 *
351
 * @param null|string $filter Optional. Filter to check. Defaults to null, which
352
 *                            checks if any filter is currently being run.
353
 * @return bool Whether the filter is currently in the stack.
354
 */
355
function doing_filter( $filter = null ) {
356
	global $wp_current_filter;
357
358
	if ( null === $filter ) {
359
		return ! empty( $wp_current_filter );
360
	}
361
362
	return in_array( $filter, $wp_current_filter );
363
}
364
365
/**
366
 * Retrieve the name of an action currently being processed.
367
 *
368
 * @since 3.9.0
369
 *
370
 * @param string|null $action Optional. Action to check. Defaults to null, which checks
371
 *                            if any action is currently being run.
372
 * @return bool Whether the action is currently in the stack.
373
 */
374
function doing_action( $action = null ) {
375
	return doing_filter( $action );
376
}
377
378
/**
379
 * Hooks a function on to a specific action.
380
 *
381
 * Actions are the hooks that the WordPress core launches at specific points
382
 * during execution, or when specific events occur. Plugins can specify that
383
 * one or more of its PHP functions are executed at these points, using the
384
 * Action API.
385
 *
386
 * @since 1.2.0
387
 *
388
 * @param string   $tag             The name of the action to which the $function_to_add is hooked.
389
 * @param callable $function_to_add The name of the function you wish to be called.
390
 * @param int      $priority        Optional. Used to specify the order in which the functions
391
 *                                  associated with a particular action are executed. Default 10.
392
 *                                  Lower numbers correspond with earlier execution,
393
 *                                  and functions with the same priority are executed
394
 *                                  in the order in which they were added to the action.
395
 * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
396
 * @return true Will always return true.
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
397
 */
398
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
399
	return add_filter($tag, $function_to_add, $priority, $accepted_args);
400
}
401
402
/**
403
 * Execute functions hooked on a specific action hook.
404
 *
405
 * This function invokes all functions attached to action hook `$tag`. It is
406
 * possible to create new action hooks by simply calling this function,
407
 * specifying the name of the new hook using the `$tag` parameter.
408
 *
409
 * You can pass extra arguments to the hooks, much like you can with apply_filters().
410
 *
411
 * @since 1.2.0
412
 *
413
 * @global array $wp_filter         Stores all of the filters
414
 * @global array $wp_actions        Increments the amount of times action was triggered.
415
 * @global array $wp_current_filter Stores the list of current filters with the current one last
416
 *
417
 * @param string $tag     The name of the action to be executed.
418
 * @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...
419
 *                        functions hooked to the action. Default empty.
420
 */
421
function do_action($tag, $arg = '') {
422
	global $wp_filter, $wp_actions, $wp_current_filter;
423
424 View Code Duplication
	if ( ! isset($wp_actions[$tag]) )
425
		$wp_actions[$tag] = 1;
426
	else
427
		++$wp_actions[$tag];
428
429
	// Do 'all' actions first
430 View Code Duplication
	if ( isset($wp_filter['all']) ) {
431
		$wp_current_filter[] = $tag;
432
		$all_args = func_get_args();
433
		_wp_call_all_hook($all_args);
434
	}
435
436
	if ( !isset($wp_filter[$tag]) ) {
437
		if ( isset($wp_filter['all']) )
438
			array_pop($wp_current_filter);
439
		return;
440
	}
441
442
	if ( !isset($wp_filter['all']) )
443
		$wp_current_filter[] = $tag;
444
445
	$args = array();
446
	if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
447
		$args[] =& $arg[0];
448
	else
449
		$args[] = $arg;
450
	for ( $a = 2, $num = func_num_args(); $a < $num; $a++ )
451
		$args[] = func_get_arg($a);
452
453
	$wp_filter[ $tag ]->do_action( $args );
454
455
	array_pop($wp_current_filter);
456
}
457
458
/**
459
 * Retrieve the number of times an action is fired.
460
 *
461
 * @since 2.1.0
462
 *
463
 * @global array $wp_actions Increments the amount of times action was triggered.
464
 *
465
 * @param string $tag The name of the action hook.
466
 * @return int The number of times action hook $tag is fired.
467
 */
468
function did_action($tag) {
469
	global $wp_actions;
470
471
	if ( ! isset( $wp_actions[ $tag ] ) )
472
		return 0;
473
474
	return $wp_actions[$tag];
475
}
476
477
/**
478
 * Execute functions hooked on a specific action hook, specifying arguments in an array.
479
 *
480
 * @since 2.1.0
481
 *
482
 * @see do_action() This function is identical, but the arguments passed to the
483
 *                  functions hooked to $tag< are supplied using an array.
484
 * @global array $wp_filter         Stores all of the filters
485
 * @global array $wp_actions        Increments the amount of times action was triggered.
486
 * @global array $wp_current_filter Stores the list of current filters with the current one last
487
 *
488
 * @param string $tag  The name of the action to be executed.
489
 * @param array  $args The arguments supplied to the functions hooked to `$tag`.
490
 */
491
function do_action_ref_array($tag, $args) {
492
	global $wp_filter, $wp_actions, $wp_current_filter;
493
494 View Code Duplication
	if ( ! isset($wp_actions[$tag]) )
495
		$wp_actions[$tag] = 1;
496
	else
497
		++$wp_actions[$tag];
498
499
	// Do 'all' actions first
500 View Code Duplication
	if ( isset($wp_filter['all']) ) {
501
		$wp_current_filter[] = $tag;
502
		$all_args = func_get_args();
503
		_wp_call_all_hook($all_args);
504
	}
505
506
	if ( !isset($wp_filter[$tag]) ) {
507
		if ( isset($wp_filter['all']) )
508
			array_pop($wp_current_filter);
509
		return;
510
	}
511
512
	if ( !isset($wp_filter['all']) )
513
		$wp_current_filter[] = $tag;
514
515
	$wp_filter[ $tag ]->do_action( $args );
516
517
	array_pop($wp_current_filter);
518
}
519
520
/**
521
 * Check if any action has been registered for a hook.
522
 *
523
 * @since 2.5.0
524
 *
525
 * @see has_filter() has_action() is an alias of has_filter().
526
 *
527
 * @param string        $tag               The name of the action hook.
528
 * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
529
 * @return bool|int If $function_to_check is omitted, returns boolean for whether the hook has
0 ignored issues
show
Consider making the return type a bit more specific; maybe use false|integer.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
530
 *                  anything registered. When checking a specific function, the priority of that
531
 *                  hook is returned, or false if the function is not attached. When using the
532
 *                  $function_to_check argument, this function may return a non-boolean value
533
 *                  that evaluates to false (e.g.) 0, so use the === operator for testing the
534
 *                  return value.
535
 */
536
function has_action($tag, $function_to_check = false) {
537
	return has_filter($tag, $function_to_check);
538
}
539
540
/**
541
 * Removes a function from a specified action hook.
542
 *
543
 * This function removes a function attached to a specified action hook. This
544
 * method can be used to remove default functions attached to a specific filter
545
 * hook and possibly replace them with a substitute.
546
 *
547
 * @since 1.2.0
548
 *
549
 * @param string   $tag                The action hook to which the function to be removed is hooked.
550
 * @param callable $function_to_remove The name of the function which should be removed.
551
 * @param int      $priority           Optional. The priority of the function. Default 10.
552
 * @return bool Whether the function is removed.
553
 */
554
function remove_action( $tag, $function_to_remove, $priority = 10 ) {
555
	return remove_filter( $tag, $function_to_remove, $priority );
556
}
557
558
/**
559
 * Remove all of the hooks from an action.
560
 *
561
 * @since 2.7.0
562
 *
563
 * @param string   $tag      The action to remove hooks from.
564
 * @param int|bool $priority The priority number to remove them from. Default false.
565
 * @return true True when finished.
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
566
 */
567
function remove_all_actions($tag, $priority = false) {
568
	return remove_all_filters($tag, $priority);
569
}
570
571
/**
572
 * Fires functions attached to a deprecated filter hook.
573
 *
574
 * When a filter hook is deprecated, the apply_filters() call is replaced with
575
 * apply_filters_deprecated(), which triggers a deprecation notice and then fires
576
 * the original filter hook.
577
 *
578
 * @since 4.6.0
579
 *
580
 * @see _deprecated_hook()
581
 *
582
 * @param string $tag         The name of the filter hook.
583
 * @param array  $args        Array of additional function arguments to be passed to apply_filters().
584
 * @param string $version     The version of WordPress that deprecated the hook.
585
 * @param string $replacement Optional. The hook that should have been used. Default false.
586
 * @param string $message     Optional. A message regarding the change. Default null.
587
 */
588
function apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
589
	if ( ! has_filter( $tag ) ) {
590
		return $args[0];
591
	}
592
593
	_deprecated_hook( $tag, $version, $replacement, $message );
0 ignored issues
show
It seems like $replacement defined by parameter $replacement on line 588 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...
594
595
	return apply_filters_ref_array( $tag, $args );
596
}
597
598
/**
599
 * Fires functions attached to a deprecated action hook.
600
 *
601
 * When an action hook is deprecated, the do_action() call is replaced with
602
 * do_action_deprecated(), which triggers a deprecation notice and then fires
603
 * the original hook.
604
 *
605
 * @since 4.6.0
606
 *
607
 * @see _deprecated_hook()
608
 *
609
 * @param string $tag         The name of the action hook.
610
 * @param array  $args        Array of additional function arguments to be passed to do_action().
611
 * @param string $version     The version of WordPress that deprecated the hook.
612
 * @param string $replacement Optional. The hook that should have been used.
613
 * @param string $message     Optional. A message regarding the change.
614
 */
615
function do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
616
	if ( ! has_action( $tag ) ) {
617
		return;
618
	}
619
620
	_deprecated_hook( $tag, $version, $replacement, $message );
0 ignored issues
show
It seems like $replacement defined by parameter $replacement on line 615 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...
621
622
	do_action_ref_array( $tag, $args );
623
}
624
625
//
626
// Functions for handling plugins.
627
//
628
629
/**
630
 * Gets the basename of a plugin.
631
 *
632
 * This method extracts the name of a plugin from its filename.
633
 *
634
 * @since 1.5.0
635
 *
636
 * @global array $wp_plugin_paths
637
 *
638
 * @param string $file The filename of plugin.
639
 * @return string The name of a plugin.
640
 */
641
function plugin_basename( $file ) {
642
	global $wp_plugin_paths;
643
644
	// $wp_plugin_paths contains normalized paths.
645
	$file = wp_normalize_path( $file );
646
647
	arsort( $wp_plugin_paths );
648
	foreach ( $wp_plugin_paths as $dir => $realdir ) {
649
		if ( strpos( $file, $realdir ) === 0 ) {
650
			$file = $dir . substr( $file, strlen( $realdir ) );
651
		}
652
	}
653
654
	$plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
655
	$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
656
657
	$file = preg_replace('#^' . preg_quote($plugin_dir, '#') . '/|^' . preg_quote($mu_plugin_dir, '#') . '/#','',$file); // get relative path from plugins dir
658
	$file = trim($file, '/');
659
	return $file;
660
}
661
662
/**
663
 * Register a plugin's real path.
664
 *
665
 * This is used in plugin_basename() to resolve symlinked paths.
666
 *
667
 * @since 3.9.0
668
 *
669
 * @see wp_normalize_path()
670
 *
671
 * @global array $wp_plugin_paths
672
 *
673
 * @staticvar string $wp_plugin_path
674
 * @staticvar string $wpmu_plugin_path
675
 *
676
 * @param string $file Known path to the file.
677
 * @return bool Whether the path was able to be registered.
678
 */
679
function wp_register_plugin_realpath( $file ) {
680
	global $wp_plugin_paths;
681
682
	// Normalize, but store as static to avoid recalculation of a constant value
683
	static $wp_plugin_path = null, $wpmu_plugin_path = null;
684
	if ( ! isset( $wp_plugin_path ) ) {
685
		$wp_plugin_path   = wp_normalize_path( WP_PLUGIN_DIR   );
686
		$wpmu_plugin_path = wp_normalize_path( WPMU_PLUGIN_DIR );
687
	}
688
689
	$plugin_path = wp_normalize_path( dirname( $file ) );
690
	$plugin_realpath = wp_normalize_path( dirname( realpath( $file ) ) );
691
692
	if ( $plugin_path === $wp_plugin_path || $plugin_path === $wpmu_plugin_path ) {
693
		return false;
694
	}
695
696
	if ( $plugin_path !== $plugin_realpath ) {
697
		$wp_plugin_paths[ $plugin_path ] = $plugin_realpath;
698
	}
699
700
	return true;
701
}
702
703
/**
704
 * Get the filesystem directory path (with trailing slash) for the plugin __FILE__ passed in.
705
 *
706
 * @since 2.8.0
707
 *
708
 * @param string $file The filename of the plugin (__FILE__).
709
 * @return string the filesystem path of the directory that contains the plugin.
710
 */
711
function plugin_dir_path( $file ) {
712
	return trailingslashit( dirname( $file ) );
713
}
714
715
/**
716
 * Get the URL directory path (with trailing slash) for the plugin __FILE__ passed in.
717
 *
718
 * @since 2.8.0
719
 *
720
 * @param string $file The filename of the plugin (__FILE__).
721
 * @return string the URL path of the directory that contains the plugin.
722
 */
723
function plugin_dir_url( $file ) {
724
	return trailingslashit( plugins_url( '', $file ) );
725
}
726
727
/**
728
 * Set the activation hook for a plugin.
729
 *
730
 * When a plugin is activated, the action 'activate_PLUGINNAME' hook is
731
 * called. In the name of this hook, PLUGINNAME is replaced with the name
732
 * of the plugin, including the optional subdirectory. For example, when the
733
 * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
734
 * the name of this hook will become 'activate_sampleplugin/sample.php'.
735
 *
736
 * When the plugin consists of only one file and is (as by default) located at
737
 * wp-content/plugins/sample.php the name of this hook will be
738
 * 'activate_sample.php'.
739
 *
740
 * @since 2.0.0
741
 *
742
 * @param string   $file     The filename of the plugin including the path.
743
 * @param callable $function The function hooked to the 'activate_PLUGIN' action.
744
 */
745
function register_activation_hook($file, $function) {
746
	$file = plugin_basename($file);
747
	add_action('activate_' . $file, $function);
748
}
749
750
/**
751
 * Set the deactivation hook for a plugin.
752
 *
753
 * When a plugin is deactivated, the action 'deactivate_PLUGINNAME' hook is
754
 * called. In the name of this hook, PLUGINNAME is replaced with the name
755
 * of the plugin, including the optional subdirectory. For example, when the
756
 * plugin is located in wp-content/plugins/sampleplugin/sample.php, then
757
 * the name of this hook will become 'deactivate_sampleplugin/sample.php'.
758
 *
759
 * When the plugin consists of only one file and is (as by default) located at
760
 * wp-content/plugins/sample.php the name of this hook will be
761
 * 'deactivate_sample.php'.
762
 *
763
 * @since 2.0.0
764
 *
765
 * @param string   $file     The filename of the plugin including the path.
766
 * @param callable $function The function hooked to the 'deactivate_PLUGIN' action.
767
 */
768
function register_deactivation_hook($file, $function) {
769
	$file = plugin_basename($file);
770
	add_action('deactivate_' . $file, $function);
771
}
772
773
/**
774
 * Set the uninstallation hook for a plugin.
775
 *
776
 * Registers the uninstall hook that will be called when the user clicks on the
777
 * uninstall link that calls for the plugin to uninstall itself. The link won't
778
 * be active unless the plugin hooks into the action.
779
 *
780
 * The plugin should not run arbitrary code outside of functions, when
781
 * registering the uninstall hook. In order to run using the hook, the plugin
782
 * will have to be included, which means that any code laying outside of a
783
 * function will be run during the uninstall process. The plugin should not
784
 * hinder the uninstall process.
785
 *
786
 * If the plugin can not be written without running code within the plugin, then
787
 * the plugin should create a file named 'uninstall.php' in the base plugin
788
 * folder. This file will be called, if it exists, during the uninstall process
789
 * bypassing the uninstall hook. The plugin, when using the 'uninstall.php'
790
 * should always check for the 'WP_UNINSTALL_PLUGIN' constant, before
791
 * executing.
792
 *
793
 * @since 2.7.0
794
 *
795
 * @param string   $file     Plugin file.
796
 * @param callable $callback The callback to run when the hook is called. Must be
797
 *                           a static method or function.
798
 */
799
function register_uninstall_hook( $file, $callback ) {
800
	if ( is_array( $callback ) && is_object( $callback[0] ) ) {
801
		_doing_it_wrong( __FUNCTION__, __( 'Only a static class method or function can be used in an uninstall hook.' ), '3.1.0' );
802
		return;
803
	}
804
805
	/*
806
	 * The option should not be autoloaded, because it is not needed in most
807
	 * cases. Emphasis should be put on using the 'uninstall.php' way of
808
	 * uninstalling the plugin.
809
	 */
810
	$uninstallable_plugins = (array) get_option('uninstall_plugins');
811
	$uninstallable_plugins[plugin_basename($file)] = $callback;
812
813
	update_option('uninstall_plugins', $uninstallable_plugins);
814
}
815
816
/**
817
 * Call the 'all' hook, which will process the functions hooked into it.
818
 *
819
 * The 'all' hook passes all of the arguments or parameters that were used for
820
 * the hook, which this function was called for.
821
 *
822
 * This function is used internally for apply_filters(), do_action(), and
823
 * do_action_ref_array() and is not meant to be used from outside those
824
 * functions. This function does not check for the existence of the all hook, so
825
 * it will fail unless the all hook exists prior to this function call.
826
 *
827
 * @since 2.5.0
828
 * @access private
829
 *
830
 * @global array $wp_filter  Stores all of the filters
831
 *
832
 * @param array $args The collected parameters from the hook that was called.
833
 */
834
function _wp_call_all_hook($args) {
835
	global $wp_filter;
836
837
	$wp_filter['all']->do_all_hook( $args );
838
}
839
840
/**
841
 * Build Unique ID for storage and retrieval.
842
 *
843
 * The old way to serialize the callback caused issues and this function is the
844
 * solution. It works by checking for objects and creating a new property in
845
 * the class to keep track of the object and new objects of the same class that
846
 * need to be added.
847
 *
848
 * It also allows for the removal of actions and filters for objects after they
849
 * change class properties. It is possible to include the property $wp_filter_id
850
 * in your class and set it to "null" or a number to bypass the workaround.
851
 * However this will prevent you from adding new classes and any new classes
852
 * will overwrite the previous hook by the same class.
853
 *
854
 * Functions and static method callbacks are just returned as strings and
855
 * shouldn't have any speed penalty.
856
 *
857
 * @link https://core.trac.wordpress.org/ticket/3875
858
 *
859
 * @since 2.2.3
860
 * @access private
861
 *
862
 * @global array $wp_filter Storage for all of the filters and actions.
863
 * @staticvar int $filter_id_count
864
 *
865
 * @param string   $tag      Used in counting how many hooks were applied
866
 * @param callable $function Used for creating unique id
867
 * @param int|bool $priority Used in counting how many hooks were applied. If === false
868
 *                           and $function is an object reference, we return the unique
869
 *                           id only if it already has one, false otherwise.
870
 * @return string|false Unique ID for usage as array key or false if $priority === false
0 ignored issues
show
Should the return type not be string|false|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
871
 *                      and $function is an object reference, and it does not already have
872
 *                      a unique id.
873
 */
874
function _wp_filter_build_unique_id($tag, $function, $priority) {
875
	global $wp_filter;
876
	static $filter_id_count = 0;
877
878
	if ( is_string($function) )
879
		return $function;
880
881 View Code Duplication
	if ( is_object($function) ) {
882
		// Closures are currently implemented as objects
883
		$function = array( $function, '' );
884
	} else {
885
		$function = (array) $function;
886
	}
887
888
	if (is_object($function[0]) ) {
889
		// Object Class Calling
890
		if ( function_exists('spl_object_hash') ) {
891
			return spl_object_hash($function[0]) . $function[1];
892
		} else {
893
			$obj_idx = get_class($function[0]).$function[1];
894
			if ( !isset($function[0]->wp_filter_id) ) {
895
				if ( false === $priority )
896
					return false;
897
				$obj_idx .= isset($wp_filter[$tag][$priority]) ? count((array)$wp_filter[$tag][$priority]) : $filter_id_count;
898
				$function[0]->wp_filter_id = $filter_id_count;
899
				++$filter_id_count;
900
			} else {
901
				$obj_idx .= $function[0]->wp_filter_id;
902
			}
903
904
			return $obj_idx;
905
		}
906
	} elseif ( is_string( $function[0] ) ) {
907
		// Static Calling
908
		return $function[0] . '::' . $function[1];
909
	}
910
}
911