Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/woocomme.../src/Utilitie...
File: CallbackUtil.php
<?php
[0] Fix | Delete
declare(strict_types=1);
[1] Fix | Delete
[2] Fix | Delete
namespace Automattic\WooCommerce\Utilities;
[3] Fix | Delete
[4] Fix | Delete
/**
[5] Fix | Delete
* Utility class for working with WordPress hooks and callbacks.
[6] Fix | Delete
*
[7] Fix | Delete
* @since 10.5.0
[8] Fix | Delete
*/
[9] Fix | Delete
final class CallbackUtil {
[10] Fix | Delete
[11] Fix | Delete
/**
[12] Fix | Delete
* Get a stable signature for a callback that can be used for hashing.
[13] Fix | Delete
*
[14] Fix | Delete
* This method normalizes callbacks into consistent string representations,
[15] Fix | Delete
* regardless of changes in dynamic properties in callback instances.
[16] Fix | Delete
*
[17] Fix | Delete
* @param callable|mixed $callback A PHP callback.
[18] Fix | Delete
* @return string Normalized callback signature.
[19] Fix | Delete
*
[20] Fix | Delete
* @since 10.5.0
[21] Fix | Delete
*/
[22] Fix | Delete
public static function get_callback_signature( $callback ): string {
[23] Fix | Delete
if ( is_string( $callback ) ) {
[24] Fix | Delete
// Standalone function.
[25] Fix | Delete
return $callback;
[26] Fix | Delete
}
[27] Fix | Delete
[28] Fix | Delete
if ( is_array( $callback ) && 2 === count( $callback ) ) {
[29] Fix | Delete
$target = $callback[0];
[30] Fix | Delete
$method = $callback[1];
[31] Fix | Delete
[32] Fix | Delete
if ( ( is_object( $target ) || is_string( $target ) ) && is_string( $method ) ) {
[33] Fix | Delete
// Array callback (class method).
[34] Fix | Delete
$class = is_object( $target ) ? get_class( $target ) : $target;
[35] Fix | Delete
return "{$class}::{$method}";
[36] Fix | Delete
}
[37] Fix | Delete
}
[38] Fix | Delete
[39] Fix | Delete
if ( $callback instanceof \Closure ) {
[40] Fix | Delete
// Closure.
[41] Fix | Delete
try {
[42] Fix | Delete
return self::get_closure_signature( $callback );
[43] Fix | Delete
} catch ( \Exception $e ) {
[44] Fix | Delete
return 'Closure@' . spl_object_hash( $callback );
[45] Fix | Delete
}
[46] Fix | Delete
}
[47] Fix | Delete
[48] Fix | Delete
if ( is_object( $callback ) ) {
[49] Fix | Delete
// Invokable object.
[50] Fix | Delete
try {
[51] Fix | Delete
return self::get_invokable_signature( $callback );
[52] Fix | Delete
} catch ( \Exception $e ) {
[53] Fix | Delete
return get_class( $callback ) . '::__invoke';
[54] Fix | Delete
}
[55] Fix | Delete
}
[56] Fix | Delete
[57] Fix | Delete
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- Fallback for unknown callback types.
[58] Fix | Delete
return serialize( $callback );
[59] Fix | Delete
}
[60] Fix | Delete
[61] Fix | Delete
/**
[62] Fix | Delete
* Get signatures for all callbacks attached to a specific hook.
[63] Fix | Delete
*
[64] Fix | Delete
* Returns an array of callback signatures for all callbacks registered
[65] Fix | Delete
* with the specified hook name, organized by priority. This is useful
[66] Fix | Delete
* for generating cache keys or comparing hook state.
[67] Fix | Delete
*
[68] Fix | Delete
* Closure signatures are based on their file location and line numbers,
[69] Fix | Delete
* providing consistent hashes across requests for the same closure code.
[70] Fix | Delete
*
[71] Fix | Delete
* @param string $hook_name The name of the hook to inspect.
[72] Fix | Delete
* @return array<int, array<string>> Array of priority => array( signatures ), empty if hook has no callbacks.
[73] Fix | Delete
*
[74] Fix | Delete
* @since 10.5.0
[75] Fix | Delete
*/
[76] Fix | Delete
public static function get_hook_callback_signatures( string $hook_name ): array {
[77] Fix | Delete
global $wp_filter;
[78] Fix | Delete
[79] Fix | Delete
if ( ! isset( $wp_filter[ $hook_name ] ) ) {
[80] Fix | Delete
return array();
[81] Fix | Delete
}
[82] Fix | Delete
[83] Fix | Delete
$result = array();
[84] Fix | Delete
[85] Fix | Delete
foreach ( $wp_filter[ $hook_name ]->callbacks as $priority => $priority_callbacks ) {
[86] Fix | Delete
$result[ $priority ] = array_map(
[87] Fix | Delete
fn( $callback_data ) => self::get_callback_signature( $callback_data['function'] ),
[88] Fix | Delete
array_values( $priority_callbacks )
[89] Fix | Delete
);
[90] Fix | Delete
}
[91] Fix | Delete
[92] Fix | Delete
return $result;
[93] Fix | Delete
}
[94] Fix | Delete
[95] Fix | Delete
/**
[96] Fix | Delete
* Get a stable signature for a closure based on its file path and line numbers.
[97] Fix | Delete
*
[98] Fix | Delete
* @param \Closure $closure The closure to generate a signature for.
[99] Fix | Delete
* @return string Signature in the format 'Closure@filename:startLine-endLine'.
[100] Fix | Delete
* @throws \ReflectionException If reflection fails.
[101] Fix | Delete
*/
[102] Fix | Delete
private static function get_closure_signature( \Closure $closure ): string {
[103] Fix | Delete
$reflection = new \ReflectionFunction( $closure );
[104] Fix | Delete
$file = $reflection->getFileName();
[105] Fix | Delete
$start = $reflection->getStartLine();
[106] Fix | Delete
$end = $reflection->getEndLine();
[107] Fix | Delete
[108] Fix | Delete
if ( false === $file || false === $start || false === $end ) {
[109] Fix | Delete
throw new \ReflectionException( 'Unable to get closure location information' );
[110] Fix | Delete
}
[111] Fix | Delete
[112] Fix | Delete
return sprintf( 'Closure@%s:%d-%d', $file, $start, $end );
[113] Fix | Delete
}
[114] Fix | Delete
[115] Fix | Delete
/**
[116] Fix | Delete
* Get a stable signature for an invokable object based on its class and __invoke method location.
[117] Fix | Delete
*
[118] Fix | Delete
* For regular classes, returns 'ClassName::__invoke' since the class name is stable.
[119] Fix | Delete
* For anonymous classes, includes file location since the class name varies between requests.
[120] Fix | Delete
*
[121] Fix | Delete
* @param object $invokable The invokable object to generate a signature for.
[122] Fix | Delete
* @return string Signature in format 'ClassName::__invoke' or 'class@anonymous[hash]::__invoke@filename:startLine-endLine'.
[123] Fix | Delete
*/
[124] Fix | Delete
private static function get_invokable_signature( object $invokable ): string {
[125] Fix | Delete
$method = new \ReflectionMethod( $invokable, '__invoke' );
[126] Fix | Delete
$class = $method->getDeclaringClass();
[127] Fix | Delete
[128] Fix | Delete
if ( ! $class->isAnonymous() ) {
[129] Fix | Delete
return $class->getName() . '::__invoke';
[130] Fix | Delete
}
[131] Fix | Delete
[132] Fix | Delete
return sprintf(
[133] Fix | Delete
'class@anonymous[%s]::__invoke@%s:%d-%d',
[134] Fix | Delete
md5( $class->getName() ),
[135] Fix | Delete
$method->getFileName(),
[136] Fix | Delete
$method->getStartLine(),
[137] Fix | Delete
$method->getEndLine()
[138] Fix | Delete
);
[139] Fix | Delete
}
[140] Fix | Delete
}
[141] Fix | Delete
[142] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function