<?php
/**
 * VMPFence cURL Interceptor
 * 
 * Allows interception and modification of cURL options for HTTP requests
 *
 * @package VMPFence
 * @since 2.2.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Exception thrown when cURL interception fails
 */
class VMPFence_Curl_Interception_Failed_Exception extends RuntimeException {
}

/**
 * cURL Interceptor class
 * 
 * Hooks into WordPress HTTP API to modify cURL options
 */
class VMPFence_Curl_Interceptor {

    const HOOK_NAME = 'http_api_curl';

    private $handle = null;
    private $options = array();
    private $requireInterception;

    /**
     * Constructor
     *
     * @param bool $requireInterception Whether to throw exception if interception fails
     */
    public function __construct($requireInterception = true) {
        $this->requireInterception = $requireInterception;
    }

    /**
     * Reset the interceptor state
     */
    private function reset() {
        $this->handle = null;
    }

    /**
     * Set a cURL option to be applied
     *
     * @param int $option cURL option constant
     * @param mixed $value Option value
     */
    public function setOption($option, $value) {
        $this->options[$option] = $value;
    }

    /**
     * Get the cURL handle
     *
     * @return resource|null
     */
    public function getHandle() {
        return $this->handle;
    }

    /**
     * Handle the HTTP API cURL hook
     *
     * @param resource $handle cURL handle
     */
    public function handleHook($handle) {
        $this->handle = $handle;
        curl_setopt_array($handle, $this->options);
    }

    /**
     * Intercept a callable and apply cURL options
     *
     * @param callable $callable Function to execute with intercepted cURL
     * @return mixed Result of callable
     * @throws VMPFence_Curl_Interception_Failed_Exception
     */
    public function intercept($callable) {
        $this->reset();
        $action = array($this, 'handleHook');
        add_action(self::HOOK_NAME, $action);
        $result = $callable();
        if ($this->handle === null && $this->requireInterception) {
            throw new VMPFence_Curl_Interception_Failed_Exception('Hook was not invoked with a valid cURL handle');
        }
        remove_action(self::HOOK_NAME, $action);
        return $result;
    }
}
