<?php
/**
 * Request Data Helper
 *
 * @package AmbassadorHub\Support
 */

namespace AmbassadorHub\Support;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Helpers for safely handing request superglobals to third-party code.
 */
final class RequestData {

	/**
	 * Return a deep-sanitized, unslashed copy of a request array (e.g. $_POST),
	 * suitable for passing to action/filter hooks that extensions may consume.
	 *
	 * This does not replace field-specific sanitization/validation already
	 * performed on values the plugin itself reads and uses — it exists so that
	 * hook callbacks (ours or a third party's) never receive the raw
	 * superglobal, which may be echoed, stored, or otherwise trusted without
	 * further checks downstream.
	 *
	 * @param array         $data          Raw request array (e.g. $_POST).
	 * @param array<string> $exclude_keys  Top-level keys to drop entirely rather
	 *                                     than sanitize as text — e.g. plaintext
	 *                                     passwords, which sanitize_text_field()
	 *                                     would otherwise alter or leak into a
	 *                                     hook's args.
	 *
	 * @return array
	 */
	public static function sanitized_copy( array $data, array $exclude_keys = array() ): array {
		foreach ( $exclude_keys as $key ) {
			unset( $data[ $key ] );
		}

		$unslashed = wp_unslash( $data );

		return map_deep( $unslashed, array( self::class, 'sanitize_scalar' ) );
	}

	/**
	 * map_deep() callback: sanitize a single scalar value as text.
	 *
	 * Non-scalars (already-recursed arrays) pass through unchanged.
	 *
	 * @param mixed $value Value to sanitize.
	 *
	 * @return mixed
	 */
	public static function sanitize_scalar( $value ) {
		if ( ! is_scalar( $value ) ) {
			return $value;
		}

		return sanitize_text_field( (string) $value );
	}
}
