<?php

class Curl {
    protected $_ch;
    protected $_options;

    /**
     * Create a new Curl Handle.
     *
     * Example usage:
     * $curl = new Curl('http://www.example.com');
     * // $curl->setOption(CURLOPT_CONNECTTIMEOUT, 2);
     * $html = $curl->exec();
     * // $status = $curl->getInfo(CURLINFO_HTTP_CODE);
     * // unset($curl);
     *
     * @param string $url
     */
    public function __construct($url = null) {
        $this->_ch = curl_init();
        if ($url) {
            $this->setOption(CURLOPT_URL, $url);
        }
    }

    /**
     * Stores curl options in an array. Use the constants from curl (e. g.
     * CURLOPT_CONNECTTIMEOUT).
     *
     * @see curl_setopt()
     * @param int $option
     * @param $value
     */
    public function setOption($option, $value) {
        $this->_options[$option] = $value;
    }

    /**
     * Stores an array of curl options.
     *
     * @param array $options
     */
    public function setOptions(array $options) {
        foreach ($options as $option => $value) {
            $this->setOption($option, $value);
        }
    }

    /**
     * Returns the current value of the curl option if previously set.
     *
     * @param int $option
     * @return mixed
     */
    public function getOption($option) {
        return isset($this->_options[$option]) ? $this->_options[$option] : null;
    }

    /**
     * Sets the options to the curl handler, executes the request and returns the body from the response.
     *
     * It also forces CURLOPT_RETURNTRANSFER => true
     *
     * @return string
     * @throws Exception
     * @codeCoverageIgnore
     */
    public function exec() {
        $this->setOption(CURLOPT_RETURNTRANSFER, true);
        
        if (!$this->getOption(CURLOPT_URL)) {
            throw new Exception('No URL given');
        }

        curl_setopt_array($this->_ch, $this->_options);
        $response = curl_exec($this->_ch);

        return $response;
    }

    /**
     * Gets infos from the executed request. Use the constances from curl (e. g.
     * CURLINFO_HTTP_CODE).
     *
     * @see curl_getinfo()
     * @param int $info
     * @return mixed
     * @codeCoverageIgnore
     */
    public function getInfo($info) {
        return curl_getinfo($this->_ch, $info);
    }

    /**
     * Close the curl handle on destruction.
     *
     * @codeCoverageIgnore
     */
    public function __destruct() {
        curl_close($this->_ch);
    }
}