wp/wp-includes/class-wp-hook.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    13  * @since 4.7.0
    13  * @since 4.7.0
    14  *
    14  *
    15  * @see Iterator
    15  * @see Iterator
    16  * @see ArrayAccess
    16  * @see ArrayAccess
    17  */
    17  */
       
    18 #[AllowDynamicProperties]
    18 final class WP_Hook implements Iterator, ArrayAccess {
    19 final class WP_Hook implements Iterator, ArrayAccess {
    19 
    20 
    20 	/**
    21 	/**
    21 	 * Hook callbacks.
    22 	 * Hook callbacks.
    22 	 *
    23 	 *
    23 	 * @since 4.7.0
    24 	 * @since 4.7.0
    24 	 * @var array
    25 	 * @var array
    25 	 */
    26 	 */
    26 	public $callbacks = array();
    27 	public $callbacks = array();
       
    28 
       
    29 	/**
       
    30 	 * Priorities list.
       
    31 	 *
       
    32 	 * @since 6.4.0
       
    33 	 * @var array
       
    34 	 */
       
    35 	protected $priorities = array();
    27 
    36 
    28 	/**
    37 	/**
    29 	 * The priority keys of actively running iterations of a hook.
    38 	 * The priority keys of actively running iterations of a hook.
    30 	 *
    39 	 *
    31 	 * @since 4.7.0
    40 	 * @since 4.7.0
    75 
    84 
    76 		$priority_existed = isset( $this->callbacks[ $priority ] );
    85 		$priority_existed = isset( $this->callbacks[ $priority ] );
    77 
    86 
    78 		$this->callbacks[ $priority ][ $idx ] = array(
    87 		$this->callbacks[ $priority ][ $idx ] = array(
    79 			'function'      => $callback,
    88 			'function'      => $callback,
    80 			'accepted_args' => $accepted_args,
    89 			'accepted_args' => (int) $accepted_args,
    81 		);
    90 		);
    82 
    91 
    83 		// If we're adding a new priority to the list, put them back in sorted order.
    92 		// If we're adding a new priority to the list, put them back in sorted order.
    84 		if ( ! $priority_existed && count( $this->callbacks ) > 1 ) {
    93 		if ( ! $priority_existed && count( $this->callbacks ) > 1 ) {
    85 			ksort( $this->callbacks, SORT_NUMERIC );
    94 			ksort( $this->callbacks, SORT_NUMERIC );
    86 		}
    95 		}
       
    96 
       
    97 		$this->priorities = array_keys( $this->callbacks );
    87 
    98 
    88 		if ( $this->nesting_level > 0 ) {
    99 		if ( $this->nesting_level > 0 ) {
    89 			$this->resort_active_iterations( $priority, $priority_existed );
   100 			$this->resort_active_iterations( $priority, $priority_existed );
    90 		}
   101 		}
    91 	}
   102 	}
    99 	 *                                    for no priority being added.
   110 	 *                                    for no priority being added.
   100 	 * @param bool      $priority_existed Optional. Flag for whether the priority already existed before the new
   111 	 * @param bool      $priority_existed Optional. Flag for whether the priority already existed before the new
   101 	 *                                    filter was added. Default false.
   112 	 *                                    filter was added. Default false.
   102 	 */
   113 	 */
   103 	private function resort_active_iterations( $new_priority = false, $priority_existed = false ) {
   114 	private function resort_active_iterations( $new_priority = false, $priority_existed = false ) {
   104 		$new_priorities = array_keys( $this->callbacks );
   115 		$new_priorities = $this->priorities;
   105 
   116 
   106 		// If there are no remaining hooks, clear out all running iterations.
   117 		// If there are no remaining hooks, clear out all running iterations.
   107 		if ( ! $new_priorities ) {
   118 		if ( ! $new_priorities ) {
   108 			foreach ( $this->iterations as $index => $iteration ) {
   119 			foreach ( $this->iterations as $index => $iteration ) {
   109 				$this->iterations[ $index ] = $new_priorities;
   120 				$this->iterations[ $index ] = $new_priorities;
   183 		if ( $exists ) {
   194 		if ( $exists ) {
   184 			unset( $this->callbacks[ $priority ][ $function_key ] );
   195 			unset( $this->callbacks[ $priority ][ $function_key ] );
   185 
   196 
   186 			if ( ! $this->callbacks[ $priority ] ) {
   197 			if ( ! $this->callbacks[ $priority ] ) {
   187 				unset( $this->callbacks[ $priority ] );
   198 				unset( $this->callbacks[ $priority ] );
       
   199 
       
   200 				$this->priorities = array_keys( $this->callbacks );
   188 
   201 
   189 				if ( $this->nesting_level > 0 ) {
   202 				if ( $this->nesting_level > 0 ) {
   190 					$this->resort_active_iterations();
   203 					$this->resort_active_iterations();
   191 				}
   204 				}
   192 			}
   205 			}
   259 		if ( ! $this->callbacks ) {
   272 		if ( ! $this->callbacks ) {
   260 			return;
   273 			return;
   261 		}
   274 		}
   262 
   275 
   263 		if ( false === $priority ) {
   276 		if ( false === $priority ) {
   264 			$this->callbacks = array();
   277 			$this->callbacks  = array();
       
   278 			$this->priorities = array();
   265 		} elseif ( isset( $this->callbacks[ $priority ] ) ) {
   279 		} elseif ( isset( $this->callbacks[ $priority ] ) ) {
   266 			unset( $this->callbacks[ $priority ] );
   280 			unset( $this->callbacks[ $priority ] );
       
   281 			$this->priorities = array_keys( $this->callbacks );
   267 		}
   282 		}
   268 
   283 
   269 		if ( $this->nesting_level > 0 ) {
   284 		if ( $this->nesting_level > 0 ) {
   270 			$this->resort_active_iterations();
   285 			$this->resort_active_iterations();
   271 		}
   286 		}
   286 			return $value;
   301 			return $value;
   287 		}
   302 		}
   288 
   303 
   289 		$nesting_level = $this->nesting_level++;
   304 		$nesting_level = $this->nesting_level++;
   290 
   305 
   291 		$this->iterations[ $nesting_level ] = array_keys( $this->callbacks );
   306 		$this->iterations[ $nesting_level ] = $this->priorities;
   292 		$num_args                           = count( $args );
   307 
       
   308 		$num_args = count( $args );
   293 
   309 
   294 		do {
   310 		do {
   295 			$this->current_priority[ $nesting_level ] = current( $this->iterations[ $nesting_level ] );
   311 			$this->current_priority[ $nesting_level ] = current( $this->iterations[ $nesting_level ] );
   296 			$priority                                 = $this->current_priority[ $nesting_level ];
   312 
       
   313 			$priority = $this->current_priority[ $nesting_level ];
   297 
   314 
   298 			foreach ( $this->callbacks[ $priority ] as $the_ ) {
   315 			foreach ( $this->callbacks[ $priority ] as $the_ ) {
   299 				if ( ! $this->doing_action ) {
   316 				if ( ! $this->doing_action ) {
   300 					$args[0] = $value;
   317 					$args[0] = $value;
   301 				}
   318 				}
   302 
   319 
   303 				// Avoid the array_slice() if possible.
   320 				// Avoid the array_slice() if possible.
   304 				if ( 0 == $the_['accepted_args'] ) {
   321 				if ( 0 === $the_['accepted_args'] ) {
   305 					$value = call_user_func( $the_['function'] );
   322 					$value = call_user_func( $the_['function'] );
   306 				} elseif ( $the_['accepted_args'] >= $num_args ) {
   323 				} elseif ( $the_['accepted_args'] >= $num_args ) {
   307 					$value = call_user_func_array( $the_['function'], $args );
   324 					$value = call_user_func_array( $the_['function'], $args );
   308 				} else {
   325 				} else {
   309 					$value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int) $the_['accepted_args'] ) );
   326 					$value = call_user_func_array( $the_['function'], array_slice( $args, 0, $the_['accepted_args'] ) );
   310 				}
   327 				}
   311 			}
   328 			}
   312 		} while ( false !== next( $this->iterations[ $nesting_level ] ) );
   329 		} while ( false !== next( $this->iterations[ $nesting_level ] ) );
   313 
   330 
   314 		unset( $this->iterations[ $nesting_level ] );
   331 		unset( $this->iterations[ $nesting_level ] );
   315 		unset( $this->current_priority[ $nesting_level ] );
   332 		unset( $this->current_priority[ $nesting_level ] );
   316 
   333 
   317 		$this->nesting_level--;
   334 		--$this->nesting_level;
   318 
   335 
   319 		return $value;
   336 		return $value;
   320 	}
   337 	}
   321 
   338 
   322 	/**
   339 	/**
   343 	 *
   360 	 *
   344 	 * @param array $args Arguments to pass to the hook callbacks. Passed by reference.
   361 	 * @param array $args Arguments to pass to the hook callbacks. Passed by reference.
   345 	 */
   362 	 */
   346 	public function do_all_hook( &$args ) {
   363 	public function do_all_hook( &$args ) {
   347 		$nesting_level                      = $this->nesting_level++;
   364 		$nesting_level                      = $this->nesting_level++;
   348 		$this->iterations[ $nesting_level ] = array_keys( $this->callbacks );
   365 		$this->iterations[ $nesting_level ] = $this->priorities;
   349 
   366 
   350 		do {
   367 		do {
   351 			$priority = current( $this->iterations[ $nesting_level ] );
   368 			$priority = current( $this->iterations[ $nesting_level ] );
   352 
   369 
   353 			foreach ( $this->callbacks[ $priority ] as $the_ ) {
   370 			foreach ( $this->callbacks[ $priority ] as $the_ ) {
   354 				call_user_func_array( $the_['function'], $args );
   371 				call_user_func_array( $the_['function'], $args );
   355 			}
   372 			}
   356 		} while ( false !== next( $this->iterations[ $nesting_level ] ) );
   373 		} while ( false !== next( $this->iterations[ $nesting_level ] ) );
   357 
   374 
   358 		unset( $this->iterations[ $nesting_level ] );
   375 		unset( $this->iterations[ $nesting_level ] );
   359 		$this->nesting_level--;
   376 		--$this->nesting_level;
   360 	}
   377 	}
   361 
   378 
   362 	/**
   379 	/**
   363 	 * Return the current priority level of the currently running iteration of the hook.
   380 	 * Return the current priority level of the currently running iteration of the hook.
   364 	 *
   381 	 *
   407 	public static function build_preinitialized_hooks( $filters ) {
   424 	public static function build_preinitialized_hooks( $filters ) {
   408 		/** @var WP_Hook[] $normalized */
   425 		/** @var WP_Hook[] $normalized */
   409 		$normalized = array();
   426 		$normalized = array();
   410 
   427 
   411 		foreach ( $filters as $hook_name => $callback_groups ) {
   428 		foreach ( $filters as $hook_name => $callback_groups ) {
   412 			if ( is_object( $callback_groups ) && $callback_groups instanceof WP_Hook ) {
   429 			if ( $callback_groups instanceof WP_Hook ) {
   413 				$normalized[ $hook_name ] = $callback_groups;
   430 				$normalized[ $hook_name ] = $callback_groups;
   414 				continue;
   431 				continue;
   415 			}
   432 			}
   416 
   433 
   417 			$hook = new WP_Hook();
   434 			$hook = new WP_Hook();
   476 		if ( is_null( $offset ) ) {
   493 		if ( is_null( $offset ) ) {
   477 			$this->callbacks[] = $value;
   494 			$this->callbacks[] = $value;
   478 		} else {
   495 		} else {
   479 			$this->callbacks[ $offset ] = $value;
   496 			$this->callbacks[ $offset ] = $value;
   480 		}
   497 		}
       
   498 
       
   499 		$this->priorities = array_keys( $this->callbacks );
   481 	}
   500 	}
   482 
   501 
   483 	/**
   502 	/**
   484 	 * Unsets a specified offset.
   503 	 * Unsets a specified offset.
   485 	 *
   504 	 *
   490 	 * @param mixed $offset The offset to unset.
   509 	 * @param mixed $offset The offset to unset.
   491 	 */
   510 	 */
   492 	#[ReturnTypeWillChange]
   511 	#[ReturnTypeWillChange]
   493 	public function offsetUnset( $offset ) {
   512 	public function offsetUnset( $offset ) {
   494 		unset( $this->callbacks[ $offset ] );
   513 		unset( $this->callbacks[ $offset ] );
       
   514 		$this->priorities = array_keys( $this->callbacks );
   495 	}
   515 	}
   496 
   516 
   497 	/**
   517 	/**
   498 	 * Returns the current element.
   518 	 * Returns the current element.
   499 	 *
   519 	 *
   559 	 */
   579 	 */
   560 	#[ReturnTypeWillChange]
   580 	#[ReturnTypeWillChange]
   561 	public function rewind() {
   581 	public function rewind() {
   562 		reset( $this->callbacks );
   582 		reset( $this->callbacks );
   563 	}
   583 	}
   564 
       
   565 }
   584 }