<?php

/**
 * Helper to read request data for the endpoints.
 *
 * @package WooCommerce\PayPalCommerce\Button\Endpoint
 */
declare (strict_types=1);
namespace WooCommerce\PayPalCommerce\Button\Endpoint;

use WooCommerce\PayPalCommerce\Button\Exception\NonceValidationException;
/**
 * Class RequestData
 */
class RequestData
{
    /**
     * Enqueues the nonce fix hook.
     */
    public function enqueue_nonce_fix()
    {
        add_filter('nonce_user_logged_out', array($this, 'nonce_fix'), 100);
    }
    /**
     * Dequeues the nonce fix hook.
     */
    public function dequeue_nonce_fix()
    {
        remove_filter('nonce_user_logged_out', array($this, 'nonce_fix'), 100);
    }
    /**
     * Reads the current request.
     *
     * @param string $nonce The nonce.
     *
     * @return array
     * @throws NonceValidationException When nonce validation fails.
     */
    public function read_request(string $nonce): array
    {
        $stream = file_get_contents('php://input');
        $json = json_decode($stream, \true);
        $this->enqueue_nonce_fix();
        if (!isset($json['nonce']) || !wp_verify_nonce($json['nonce'], $nonce)) {
            remove_filter('nonce_user_logged_out', array($this, 'nonce_fix'), 100);
            throw new NonceValidationException('Could not validate nonce.');
        }
        $this->dequeue_nonce_fix();
        if (isset($json['form_encoded'])) {
            $json['form'] = array();
            parse_str($json['form_encoded'], $json['form']);
        }
        $sanitized = $this->sanitize($json);
        return $sanitized;
    }
    /**
     * WooCommerce will give you a customer object on your 2nd request. the first page
     * load will not yet have this customer object, but the ajax request will. Therefore
     * the nonce validation will fail. this fixes this problem:
     *
     * @wp-hook nonce_user_logged_out
     * @see https://github.com/woocommerce/woocommerce/blob/69e3835041113bee80379c1037e97e26815a699b/includes/class-wc-session-handler.php#L288-L296
     * @return int
     */
    public function nonce_fix(): int
    {
        return 0;
    }
    /**
     * Sanitizes the data.
     *
     * @param array $assoc_array The data array.
     *
     * @return array
     */
    private function sanitize(array $assoc_array): array
    {
        $data = array();
        foreach ((array) $assoc_array as $raw_key => $raw_value) {
            if ($raw_key === 'form_encoded') {
                $data[$raw_key] = $raw_value;
                continue;
            }
            if (!is_array($raw_value)) {
                // Not sure if it is a good idea to sanitize everything at this level,
                // but should be fine for now since we do not send any HTML or multi-line texts via ajax.
                $data[sanitize_text_field((string) $raw_key)] = sanitize_text_field((string) $raw_value);
                continue;
            }
            $data[sanitize_text_field((string) $raw_key)] = $this->sanitize($raw_value);
        }
        return $data;
    }
}
