*/ private static array $classes_total_usage = array(); /** * @var array> */ private static array $class_hooks_usage = array(); /** * @var array{estimated_time_sec:float,calls:int} */ private static array $total_usage = array( 'calls' => 0, 'estimated_time_sec' => 0, ); private static float $plugin_loaded_sec = 0; private static ?bool $is_profiler_active = null; public static function get_callback( string $source, string $hook_name, callable $callback ): callable { return self::is_active() ? fn( ...$args ) => self::execute_callback( $source, $hook_name, $callback, $args ) : $callback; } public static function plugin_loaded( float $start_timestamp ): void { if ( self::is_active() ) { self::$plugin_loaded_sec = microtime( true ) - $start_timestamp; add_action( 'shutdown', array( self::class, 'print_report' ) ); } } public static function print_report(): void { $classes_total_usage = self::get_classes_total_usage(); echo '
'; echo '
';
		// @phpcs:ignore
		print_r(self::get_total_usage() );
		echo '
'; echo '
'; echo '
';
		echo count( $classes_total_usage ) . '
'; // @phpcs:ignore print_r( $classes_total_usage ); echo '
'; echo '
'; echo '
';
		// @phpcs:ignore
		print_r(self::$class_hooks_usage );
		echo '
'; echo '
'; } /** * @return array */ private static function get_total_usage(): array { return array_merge( array( 'plugin_loaded_sec' => self::$plugin_loaded_sec, ), self::$total_usage, ); } /** * @return array */ private static function get_classes_total_usage(): array { $classes_total_usage = array(); foreach ( self::$classes_total_usage as $class => $class_total_usage ) { $hooks = self::$class_hooks_usage[ $class ] ?? array(); $classes_total_usage[ $class ] = array_merge( $class_total_usage, array( 'hooks' => array_keys( $hooks ), ) ); } uasort( $classes_total_usage, fn( array $first, array $second ) => $second['time_sec'] <=> $first['time_sec'] ); return $classes_total_usage; } private static function is_active(): bool { if ( null === self::$is_profiler_active ) { self::$is_profiler_active = defined( 'AVF_PROFILER' ) && // @phpcs:ignore isset( $_GET['_avf_profiler'] ); } return self::$is_profiler_active; } /** * @param array $args * * @return mixed */ private static function execute_callback( string $source, string $hook_name, callable $callback, array $args ) { $start_at = microtime( true ); $result = call_user_func_array( $callback, $args ); $execution_time_sec = microtime( true ) - $start_at; self::record_call( $source, $hook_name, $execution_time_sec ); return $result; } private static function record_call( string $source, string $hook_name, float $execution_time_sec ): void { self::$classes_total_usage[ $source ] ??= array( 'time_sec' => 0, 'calls' => 0, 'hooks' => array(), ); self::$class_hooks_usage[ $source ] ??= array(); self::$class_hooks_usage[ $source ][ $hook_name ] ??= array( 'time_sec' => 0, 'calls' => 0, ); self::$total_usage['calls'] += 1; // Estimated, as we can't guarantee that the current execution isn't a child to another one. self::$total_usage['estimated_time_sec'] += $execution_time_sec; self::$classes_total_usage[ $source ]['calls'] += 1; self::$classes_total_usage[ $source ]['time_sec'] += $execution_time_sec; self::$class_hooks_usage[ $source ][ $hook_name ]['calls'] += 1; self::$class_hooks_usage[ $source ][ $hook_name ]['time_sec'] += $execution_time_sec; } }