<?php
/**
 * Sanitize canvas data before server-side export.
 *
 * Strips user-supplied code fields so exports are generated server-side only.
 *
 * @package OpusPriceBuilder\Export
 */

declare(strict_types=1);

namespace OpusPriceBuilder\Export;

/**
 * Removes arbitrary code fields from canvas data submitted via REST.
 */
class CanvasSanitizer {

	/**
	 * Fields stripped from containerSettings.
	 *
	 * @var string[]
	 */
	private const CONTAINER_CODE_FIELDS = array(
		'customCss',
		'customJs',
		'customHtml',
		'useCustomHtml',
	);

	/**
	 * Fields stripped from each element.
	 *
	 * @var string[]
	 */
	private const ELEMENT_CODE_FIELDS = array(
		'customCss',
		'customJs',
		'customHtml',
		'useCustomHtml',
	);

	/**
	 * Sanitize canvas data by removing user-supplied code fields.
	 *
	 * Preset-specific styles are applied separately via presetId and PresetAssets.
	 *
	 * @param array<string, mixed> $canvas_data Raw canvas data.
	 * @return array<string, mixed> Sanitized canvas data.
	 */
	public static function sanitize( array $canvas_data ): array {
		$sanitized = $canvas_data;

		if ( isset( $sanitized['containerSettings'] ) && is_array( $sanitized['containerSettings'] ) ) {
			$sanitized['containerSettings'] = self::stripCodeFields(
				$sanitized['containerSettings'],
				self::CONTAINER_CODE_FIELDS
			);
		}

		if ( isset( $sanitized['elements'] ) && is_array( $sanitized['elements'] ) ) {
			$sanitized['elements'] = array_map(
				static function ( $element ): array {
					if ( ! is_array( $element ) ) {
						return array();
					}

					return self::stripCodeFields( $element, self::ELEMENT_CODE_FIELDS );
				},
				$sanitized['elements']
			);
		}

		return $sanitized;
	}

	/**
	 * Remove known code fields from an associative array.
	 *
	 * @param array<string, mixed> $data   Source data.
	 * @param string[]             $fields Fields to remove.
	 * @return array<string, mixed>
	 */
	private static function stripCodeFields( array $data, array $fields ): array {
		foreach ( $fields as $field ) {
			unset( $data[ $field ] );
		}

		return $data;
	}
}
