callbacks ) || ! is_array( $wp_filter[ $hook_name ]->callbacks ) ) { continue; } foreach ( $wp_filter[ $hook_name ]->callbacks as $priority => $callbacks ) { foreach ( $callbacks as $callback_id => $definition ) { if ( ! is_int( $callback_id ) ) { continue; } $safe_id = self::safe_callback_id( $definition['function'] ?? null, $callback_id ); while ( isset( $wp_filter[ $hook_name ]->callbacks[ $priority ][ $safe_id ] ) ) { $safe_id .= '-x'; } unset( $wp_filter[ $hook_name ]->callbacks[ $priority ][ $callback_id ] ); $wp_filter[ $hook_name ]->callbacks[ $priority ][ $safe_id ] = $definition; self::$repairs[] = array( 'hook' => $hook_name, 'priority' => (int) $priority, 'old_id' => $callback_id, 'new_id' => $safe_id, ); } } } self::record_repairs_once(); } private static function is_wsal_page() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; return 0 === strpos( $page, 'wsal-' ); } private static function safe_callback_id( $callback, $fallback ) { if ( is_string( $callback ) ) { $identity = $callback; } elseif ( $callback instanceof Closure ) { $identity = 'closure-' . spl_object_hash( $callback ); } elseif ( is_array( $callback ) && isset( $callback[0], $callback[1] ) ) { $owner = is_object( $callback[0] ) ? get_class( $callback[0] ) : (string) $callback[0]; $identity = $owner . '::' . (string) $callback[1]; } elseif ( is_object( $callback ) ) { $identity = get_class( $callback ) . '-' . spl_object_hash( $callback ); } else { $identity = 'callback-' . (string) $fallback; } return 'edcr-compat-' . sanitize_key( $identity ) . '-' . (string) $fallback; } private static function record_repairs_once() { if ( empty( self::$repairs ) ) { return; } $signature = hash( 'sha256', wp_json_encode( self::$repairs ) ); if ( get_transient( 'edrad_wsal_guard_' . substr( $signature, 0, 20 ) ) ) { return; } set_transient( 'edrad_wsal_guard_' . substr( $signature, 0, 20 ), 1, DAY_IN_SECONDS ); EDRAD_Database::insert_event( array( 'event_type' => 'compatibility_guard_applied', 'severity' => 2, 'summary' => 'Compatibility Shield normalized an unsafe WP Activity Log notice callback ID.', 'context' => array( 'component' => 'plugin:wp-security-audit-log', 'guard' => 'wsal_numeric_notice_callback', 'repairs' => self::$repairs, ), ) ); } }