wp/wp-includes/plugin.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
--- a/wp/wp-includes/plugin.php	Tue Oct 22 16:11:46 2019 +0200
+++ b/wp/wp-includes/plugin.php	Tue Dec 15 13:49:49 2020 +0100
@@ -8,10 +8,10 @@
  * To hook methods, you'll need to pass an array one of two ways.
  *
  * Any of the syntaxes explained in the PHP documentation for the
- * {@link https://secure.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
+ * {@link https://www.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
  * type are valid.
  *
- * Also see the {@link https://codex.wordpress.org/Plugin_API Plugin API} for
+ * Also see the {@link https://developer.wordpress.org/plugins/ Plugin API} for
  * more information and examples on how to use a lot of these functions.
  *
  * This file should have no external dependencies.
@@ -22,7 +22,7 @@
  */
 
 // Initialize the filter globals.
-require( dirname( __FILE__ ) . '/class-wp-hook.php' );
+require __DIR__ . '/class-wp-hook.php';
 
 /** @var WP_Hook[] $wp_filter */
 global $wp_filter, $wp_actions, $wp_current_filter;
@@ -93,15 +93,15 @@
  *
  * @since 0.71
  *
- * @global array $wp_filter      A multidimensional array of all hooks and the callbacks hooked to them.
+ * @global array $wp_filter A multidimensional array of all hooks and the callbacks hooked to them.
  *
  * @param string   $tag             The name of the filter to hook the $function_to_add callback to.
  * @param callable $function_to_add The callback to be run when the filter is applied.
  * @param int      $priority        Optional. Used to specify the order in which the functions
- *                                  associated with a particular action are executed. Default 10.
+ *                                  associated with a particular action are executed.
  *                                  Lower numbers correspond with earlier execution,
  *                                  and functions with the same priority are executed
- *                                  in the order in which they were added to the action.
+ *                                  in the order in which they were added to the action. Default 10.
  * @param int      $accepted_args   Optional. The number of arguments the function accepts. Default 1.
  * @return true
  */
@@ -119,7 +119,7 @@
  *
  * @since 2.5.0
  *
- * @global array $wp_filter Stores all of the filters.
+ * @global array $wp_filter Stores all of the filters and actions.
  *
  * @param string        $tag               The name of the filter hook.
  * @param callable|bool $function_to_check Optional. The callback to check for. Default false.
@@ -141,49 +141,51 @@
 }
 
 /**
- * Call the functions added to a filter hook.
+ * Calls the callback functions that have been added to a filter hook.
  *
- * The callback functions attached to filter hook $tag are invoked by calling
+ * The callback functions attached to the filter hook are invoked by calling
  * this function. This function can be used to create a new filter hook by
  * simply calling this function with the name of the new hook specified using
- * the $tag parameter.
+ * the `$tag` parameter.
  *
- * The function allows for additional arguments to be added and passed to hooks.
+ * The function also allows for multiple additional arguments to be passed to hooks.
  *
- *     // Our filter callback function
+ * Example usage:
+ *
+ *     // The filter callback function.
  *     function example_callback( $string, $arg1, $arg2 ) {
- *         // (maybe) modify $string
+ *         // (maybe) modify $string.
  *         return $string;
  *     }
  *     add_filter( 'example_filter', 'example_callback', 10, 3 );
  *
  *     /*
- *      * Apply the filters by calling the 'example_callback' function we
- *      * "hooked" to 'example_filter' using the add_filter() function above.
- *      * - 'example_filter' is the filter hook $tag
- *      * - 'filter me' is the value being filtered
+ *      * Apply the filters by calling the 'example_callback()' function
+ *      * that's hooked onto `example_filter` above.
+ *      *
+ *      * - 'example_filter' is the filter hook.
+ *      * - 'filter me' is the value being filtered.
  *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
  *     $value = apply_filters( 'example_filter', 'filter me', $arg1, $arg2 );
  *
  * @since 0.71
  *
- * @global array $wp_filter         Stores all of the filters.
+ * @global array $wp_filter         Stores all of the filters and actions.
  * @global array $wp_current_filter Stores the list of current filters with the current one last.
  *
  * @param string $tag     The name of the filter hook.
- * @param mixed  $value   The value on which the filters hooked to `$tag` are applied on.
- * @param mixed  $var,... Additional variables passed to the functions hooked to `$tag`.
+ * @param mixed  $value   The value to filter.
+ * @param mixed  ...$args Additional parameters to pass to the callback functions.
  * @return mixed The filtered value after all hooked functions are applied to it.
  */
 function apply_filters( $tag, $value ) {
 	global $wp_filter, $wp_current_filter;
 
-	$args = array();
+	$args = func_get_args();
 
 	// Do 'all' actions first.
 	if ( isset( $wp_filter['all'] ) ) {
 		$wp_current_filter[] = $tag;
-		$args                = func_get_args();
 		_wp_call_all_hook( $args );
 	}
 
@@ -198,11 +200,7 @@
 		$wp_current_filter[] = $tag;
 	}
 
-	if ( empty( $args ) ) {
-		$args = func_get_args();
-	}
-
-	// don't pass the tag name to WP_Hook
+	// Don't pass the tag name to WP_Hook.
 	array_shift( $args );
 
 	$filtered = $wp_filter[ $tag ]->apply_filters( $value, $args );
@@ -213,15 +211,15 @@
 }
 
 /**
- * Execute functions hooked on a specific filter hook, specifying arguments in an array.
+ * Calls the callback functions that have been added to a filter hook, specifying arguments in an array.
  *
  * @since 3.0.0
  *
  * @see apply_filters() This function is identical, but the arguments passed to the
  * functions hooked to `$tag` are supplied using an array.
  *
- * @global array $wp_filter         Stores all of the filters
- * @global array $wp_current_filter Stores the list of current filters with the current one last
+ * @global array $wp_filter         Stores all of the filters and actions.
+ * @global array $wp_current_filter Stores the list of current filters with the current one last.
  *
  * @param string $tag  The name of the filter hook.
  * @param array  $args The arguments supplied to the functions hooked to $tag.
@@ -230,10 +228,10 @@
 function apply_filters_ref_array( $tag, $args ) {
 	global $wp_filter, $wp_current_filter;
 
-	// Do 'all' actions first
+	// Do 'all' actions first.
 	if ( isset( $wp_filter['all'] ) ) {
 		$wp_current_filter[] = $tag;
-		$all_args            = func_get_args();
+		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
 		_wp_call_all_hook( $all_args );
 	}
 
@@ -268,7 +266,7 @@
  *
  * @since 1.2.0
  *
- * @global array $wp_filter         Stores all of the filters
+ * @global array $wp_filter Stores all of the filters and actions.
  *
  * @param string   $tag                The filter hook to which the function to be removed is hooked.
  * @param callable $function_to_remove The name of the function which should be removed.
@@ -294,7 +292,7 @@
  *
  * @since 2.7.0
  *
- * @global array $wp_filter  Stores all of the filters
+ * @global array $wp_filter Stores all of the filters and actions.
  *
  * @param string   $tag      The filter to remove hooks from.
  * @param int|bool $priority Optional. The priority number to remove. Default false.
@@ -366,7 +364,7 @@
 		return ! empty( $wp_current_filter );
 	}
 
-	return in_array( $filter, $wp_current_filter );
+	return in_array( $filter, $wp_current_filter, true );
 }
 
 /**
@@ -413,19 +411,37 @@
  * possible to create new action hooks by simply calling this function,
  * specifying the name of the new hook using the `$tag` parameter.
  *
- * You can pass extra arguments to the hooks, much like you can with apply_filters().
+ * You can pass extra arguments to the hooks, much like you can with `apply_filters()`.
+ *
+ * Example usage:
+ *
+ *     // The action callback function.
+ *     function example_callback( $arg1, $arg2 ) {
+ *         // (maybe) do something with the args.
+ *     }
+ *     add_action( 'example_action', 'example_callback', 10, 2 );
+ *
+ *     /*
+ *      * Trigger the actions by calling the 'example_callback()' function
+ *      * that's hooked onto `example_action` above.
+ *      *
+ *      * - 'example_action' is the action hook.
+ *      * - $arg1 and $arg2 are the additional arguments passed to the callback.
+ *     $value = do_action( 'example_action', $arg1, $arg2 );
  *
  * @since 1.2.0
- *
- * @global array $wp_filter         Stores all of the filters
- * @global array $wp_actions        Increments the amount of times action was triggered.
- * @global array $wp_current_filter Stores the list of current filters with the current one last
+ * @since 5.3.0 Formalized the existing and already documented `...$arg` parameter
+ *              by adding it to the function signature.
  *
- * @param string $tag     The name of the action to be executed.
- * @param mixed  $arg,... Optional. Additional arguments which are passed on to the
- *                        functions hooked to the action. Default empty.
+ * @global array $wp_filter         Stores all of the filters and actions.
+ * @global array $wp_actions        Increments the amount of times action was triggered.
+ * @global array $wp_current_filter Stores the list of current filters with the current one last.
+ *
+ * @param string $tag    The name of the action to be executed.
+ * @param mixed  ...$arg Optional. Additional arguments which are passed on to the
+ *                       functions hooked to the action. Default empty.
  */
-function do_action( $tag, $arg = '' ) {
+function do_action( $tag, ...$arg ) {
 	global $wp_filter, $wp_actions, $wp_current_filter;
 
 	if ( ! isset( $wp_actions[ $tag ] ) ) {
@@ -434,10 +450,10 @@
 		++$wp_actions[ $tag ];
 	}
 
-	// Do 'all' actions first
+	// Do 'all' actions first.
 	if ( isset( $wp_filter['all'] ) ) {
 		$wp_current_filter[] = $tag;
-		$all_args            = func_get_args();
+		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
 		_wp_call_all_hook( $all_args );
 	}
 
@@ -452,17 +468,14 @@
 		$wp_current_filter[] = $tag;
 	}
 
-	$args = array();
-	if ( is_array( $arg ) && 1 == count( $arg ) && isset( $arg[0] ) && is_object( $arg[0] ) ) { // array(&$this)
-		$args[] =& $arg[0];
-	} else {
-		$args[] = $arg;
-	}
-	for ( $a = 2, $num = func_num_args(); $a < $num; $a++ ) {
-		$args[] = func_get_arg( $a );
+	if ( empty( $arg ) ) {
+		$arg[] = '';
+	} elseif ( is_array( $arg[0] ) && 1 === count( $arg[0] ) && isset( $arg[0][0] ) && is_object( $arg[0][0] ) ) {
+		// Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`.
+		$arg[0] = $arg[0][0];
 	}
 
-	$wp_filter[ $tag ]->do_action( $args );
+	$wp_filter[ $tag ]->do_action( $arg );
 
 	array_pop( $wp_current_filter );
 }
@@ -488,15 +501,15 @@
 }
 
 /**
- * Execute functions hooked on a specific action hook, specifying arguments in an array.
+ * Calls the callback functions that have been added to an action hook, specifying arguments in an array.
  *
  * @since 2.1.0
  *
  * @see do_action() This function is identical, but the arguments passed to the
- *                  functions hooked to $tag< are supplied using an array.
- * @global array $wp_filter         Stores all of the filters
+ *                  functions hooked to `$tag` are supplied using an array.
+ * @global array $wp_filter         Stores all of the filters and actions.
  * @global array $wp_actions        Increments the amount of times action was triggered.
- * @global array $wp_current_filter Stores the list of current filters with the current one last
+ * @global array $wp_current_filter Stores the list of current filters with the current one last.
  *
  * @param string $tag  The name of the action to be executed.
  * @param array  $args The arguments supplied to the functions hooked to `$tag`.
@@ -510,10 +523,10 @@
 		++$wp_actions[ $tag ];
 	}
 
-	// Do 'all' actions first
+	// Do 'all' actions first.
 	if ( isset( $wp_filter['all'] ) ) {
 		$wp_current_filter[] = $tag;
-		$all_args            = func_get_args();
+		$all_args            = func_get_args(); // phpcs:ignore PHPCompatibility.FunctionUse.ArgumentFunctionsReportCurrentValue.NeedsInspection
 		_wp_call_all_hook( $all_args );
 	}
 
@@ -598,7 +611,7 @@
  *     return apply_filters( 'wpdocs_filter', $value, $extra_arg );
  *
  *     // Deprecated.
- *     return apply_filters_deprecated( 'wpdocs_filter', array( $value, $extra_arg ), '4.9', 'wpdocs_new_filter' );
+ *     return apply_filters_deprecated( 'wpdocs_filter', array( $value, $extra_arg ), '4.9.0', 'wpdocs_new_filter' );
  *
  * @since 4.6.0
  *
@@ -607,10 +620,10 @@
  * @param string $tag         The name of the filter hook.
  * @param array  $args        Array of additional function arguments to be passed to apply_filters().
  * @param string $version     The version of WordPress that deprecated the hook.
- * @param string $replacement Optional. The hook that should have been used. Default false.
- * @param string $message     Optional. A message regarding the change. Default null.
+ * @param string $replacement Optional. The hook that should have been used. Default empty.
+ * @param string $message     Optional. A message regarding the change. Default empty.
  */
-function apply_filters_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
+function apply_filters_deprecated( $tag, $args, $version, $replacement = '', $message = '' ) {
 	if ( ! has_filter( $tag ) ) {
 		return $args[0];
 	}
@@ -634,10 +647,10 @@
  * @param string $tag         The name of the action hook.
  * @param array  $args        Array of additional function arguments to be passed to do_action().
  * @param string $version     The version of WordPress that deprecated the hook.
- * @param string $replacement Optional. The hook that should have been used.
- * @param string $message     Optional. A message regarding the change.
+ * @param string $replacement Optional. The hook that should have been used. Default empty.
+ * @param string $message     Optional. A message regarding the change. Default empty.
  */
-function do_action_deprecated( $tag, $args, $version, $replacement = false, $message = null ) {
+function do_action_deprecated( $tag, $args, $version, $replacement = '', $message = '' ) {
 	if ( ! has_action( $tag ) ) {
 		return;
 	}
@@ -679,7 +692,8 @@
 	$plugin_dir    = wp_normalize_path( WP_PLUGIN_DIR );
 	$mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
 
-	$file = preg_replace( '#^' . preg_quote( $plugin_dir, '#' ) . '/|^' . preg_quote( $mu_plugin_dir, '#' ) . '/#', '', $file ); // get relative path from plugins dir
+	// Get relative path from plugins directory.
+	$file = preg_replace( '#^' . preg_quote( $plugin_dir, '#' ) . '/|^' . preg_quote( $mu_plugin_dir, '#' ) . '/#', '', $file );
 	$file = trim( $file, '/' );
 	return $file;
 }
@@ -695,16 +709,13 @@
  *
  * @global array $wp_plugin_paths
  *
- * @staticvar string $wp_plugin_path
- * @staticvar string $wpmu_plugin_path
- *
  * @param string $file Known path to the file.
  * @return bool Whether the path was able to be registered.
  */
 function wp_register_plugin_realpath( $file ) {
 	global $wp_plugin_paths;
 
-	// Normalize, but store as static to avoid recalculation of a constant value
+	// Normalize, but store as static to avoid recalculation of a constant value.
 	static $wp_plugin_path = null, $wpmu_plugin_path = null;
 	if ( ! isset( $wp_plugin_path ) ) {
 		$wp_plugin_path   = wp_normalize_path( WP_PLUGIN_DIR );
@@ -832,10 +843,12 @@
 	 * cases. Emphasis should be put on using the 'uninstall.php' way of
 	 * uninstalling the plugin.
 	 */
-	$uninstallable_plugins                             = (array) get_option( 'uninstall_plugins' );
-	$uninstallable_plugins[ plugin_basename( $file ) ] = $callback;
-
-	update_option( 'uninstall_plugins', $uninstallable_plugins );
+	$uninstallable_plugins = (array) get_option( 'uninstall_plugins' );
+	$plugin_basename       = plugin_basename( $file );
+	if ( ! isset( $uninstallable_plugins[ $plugin_basename ] ) || $uninstallable_plugins[ $plugin_basename ] !== $callback ) {
+		$uninstallable_plugins[ $plugin_basename ] = $callback;
+		update_option( 'uninstall_plugins', $uninstallable_plugins );
+	}
 }
 
 /**
@@ -852,7 +865,7 @@
  * @since 2.5.0
  * @access private
  *
- * @global array $wp_filter  Stores all of the filters
+ * @global array $wp_filter Stores all of the filters and actions.
  *
  * @param array $args The collected parameters from the hook that was called.
  */
@@ -882,56 +895,34 @@
  * @link https://core.trac.wordpress.org/ticket/3875
  *
  * @since 2.2.3
+ * @since 5.3.0 Removed workarounds for spl_object_hash().
+ *              `$tag` and `$priority` are no longer used,
+ *              and the function always returns a string.
  * @access private
  *
- * @global array $wp_filter Storage for all of the filters and actions.
- * @staticvar int $filter_id_count
- *
- * @param string   $tag      Used in counting how many hooks were applied
- * @param callable $function Used for creating unique id
- * @param int|bool $priority Used in counting how many hooks were applied. If === false
- *                           and $function is an object reference, we return the unique
- *                           id only if it already has one, false otherwise.
- * @return string|false Unique ID for usage as array key or false if $priority === false
- *                      and $function is an object reference, and it does not already have
- *                      a unique id.
+ * @param string   $tag      Unused. The name of the filter to build ID for.
+ * @param callable $function The function to generate ID for.
+ * @param int      $priority Unused. The order in which the functions
+ *                           associated with a particular action are executed.
+ * @return string Unique function ID for usage as array key.
  */
 function _wp_filter_build_unique_id( $tag, $function, $priority ) {
-	global $wp_filter;
-	static $filter_id_count = 0;
-
 	if ( is_string( $function ) ) {
 		return $function;
 	}
 
 	if ( is_object( $function ) ) {
-		// Closures are currently implemented as objects
+		// Closures are currently implemented as objects.
 		$function = array( $function, '' );
 	} else {
 		$function = (array) $function;
 	}
 
 	if ( is_object( $function[0] ) ) {
-		// Object Class Calling
-		if ( function_exists( 'spl_object_hash' ) ) {
-			return spl_object_hash( $function[0] ) . $function[1];
-		} else {
-			$obj_idx = get_class( $function[0] ) . $function[1];
-			if ( ! isset( $function[0]->wp_filter_id ) ) {
-				if ( false === $priority ) {
-					return false;
-				}
-				$obj_idx                  .= isset( $wp_filter[ $tag ][ $priority ] ) ? count( (array) $wp_filter[ $tag ][ $priority ] ) : $filter_id_count;
-				$function[0]->wp_filter_id = $filter_id_count;
-				++$filter_id_count;
-			} else {
-				$obj_idx .= $function[0]->wp_filter_id;
-			}
-
-			return $obj_idx;
-		}
+		// Object class calling.
+		return spl_object_hash( $function[0] ) . $function[1];
 	} elseif ( is_string( $function[0] ) ) {
-		// Static Calling
+		// Static calling.
 		return $function[0] . '::' . $function[1];
 	}
 }