<?php
/**
* Since 2013 Ovidiu Cimpean.
*
* Ovidiu Cimpean - Newsletter Pro © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at addons4prestashop@gmail.com.
*
* @author    Ovidiu Cimpean <addons4prestashop@gmail.com>
* @copyright Since 2013 Ovidiu Cimpean
* @license   Do not edit, modify or copy this file
*
* @version   Release: 4
*/

class NewsletterProCurl
{
    public $url;

    public $response;

    public $headers;

    public $config;

    public $request_params;

    public $format;

    public $errors;

    public $module;

    public function __construct($config = [])
    {
        $this->module = NewsletterPro::getInstance();
        $this->errors = [];

        if (!extension_loaded('curl')) {
            throw new Exception(sprintf($this->module->l('The availability of php %s library is not available on your server. You can talk with the hosting provider to enable it.'), 'curl'));
        }

        if (!isset($config['url'])) {
            $config['url'] = '';
        }

        $this->config = $config;
    }

    public function curlit()
    {
        if (!function_exists('curl_init')) {
            throw new Exception(sprintf($this->module->l('The availability of php %s library is not available on your server. You can talk with the hosting provider to enable it.'), 'curl'));
        } else {
            $c = curl_init();

            curl_setopt_array($c, [
                CURLOPT_USERAGENT => 'spider',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HEADER => false,

                CURLOPT_HEADERFUNCTION => [$this, 'curlHeader'],

                CURLOPT_FOLLOWLOCATION => false,
                CURLOPT_ENCODING => '',
                CURLOPT_URL => $this->url,
                CURLOPT_AUTOREFERER => true,
                CURLOPT_CONNECTTIMEOUT => 60,
                CURLOPT_TIMEOUT => 45,
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_SSL_VERIFYPEER => false,
            ]);

            switch ($this->method) {
                case 'GET':
                    $content_length = 0;
                    break;

                case 'POST':
                    curl_setopt($c, CURLOPT_POST, true);
                    $post_body = $this->safeEncode($this->xml);
                    curl_setopt($c, CURLOPT_POSTFIELDS, $post_body);
                    $this->request_params['xml'] = $post_body;
                    $content_length = Tools::strlen($post_body);
                    break;

                case 'PUT':
                    $fh = tmpfile();
                    if ('file' == $this->format) {
                        $put_body = $this->xml;
                    } else {
                        $put_body = $this->safeEncode($this->xml);
                    }

                    fwrite($fh, $put_body);
                    rewind($fh);
                    curl_setopt($c, CURLOPT_PUT, true);
                    curl_setopt($c, CURLOPT_INFILE, $fh);
                    curl_setopt($c, CURLOPT_INFILESIZE, Tools::strlen($put_body));
                    $content_length = Tools::strlen($put_body);
                    break;

                default:
                    $content_length = 0;
                    curl_setopt($c, CURLOPT_CUSTOMREQUEST, $this->method);
                    break;
            }

            if (!empty($this->request_params)) {
                if (!$this->config['multipart']) {
                    $ps = [];
                    foreach ($this->request_params as $k => $v) {
                        $ps[] = "{$k}={$v}";
                    }
                    $this->request_params = implode('&', $ps);
                }
                curl_setopt($c, CURLOPT_POSTFIELDS, $this->request_params);
            } else {
                $this->headers['Content-Type'] = '';
                $this->headers['Content-Length'] = $content_length;
            }

            $this->headers['Expect'] = '';

            if (!empty($this->headers)) {
                $headers = [];
                foreach ($this->headers as $k => $v) {
                    $headers[] = trim($k.': '.$v);
                }

                curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
            }

            if (isset($this->config['prevent_request']) && false == $this->config['prevent_request']) {
                return;
            }

            $response = curl_exec($c);
            if (false === $response) {
                $response = 'Curl error: '.curl_error($c);
                $code = 1;
            } else {
                $code = curl_getinfo($c, CURLINFO_HTTP_CODE);
            }

            $info = curl_getinfo($c);

            curl_close($c);
            if (isset($fh)) {
                fclose($fh);
            }

            $this->response['code'] = $code;
            $this->response['response'] = $response;
            $this->response['info'] = $info;
            $this->response['format'] = $this->format;

            return $code;
        }
    }

    public function url($request = '', $format = 'json')
    {
        if (isset($format)) {
            switch ($format) {
                case 'html':
                    $this->headers['Accept'] = 'text/plain';
                    break;
                case 'pdf':
                    $this->headers['Accept'] = 'application/pdf';
                    break;
                case 'json':
                    $this->headers['Accept'] = 'application/json';
                    break;
                case 'xml':
                default:
                    $this->headers['Accept'] = 'application/xml';
                    break;
            }
        }

        $this->format = $format;

        return implode([
            $this->config['url'],
            $request,
        ]);
    }

    public function request($method, $url, $params = [], $xml = '')
    {
        $multipart = false;

        if ('' !== $xml) {
            $this->xml = $xml;
        }

        if ('xml' == $method) {
            $params['xml'] = $xml;
        }

        $this->prepareMethod($method);
        $this->config['multipart'] = $multipart;

        $this->url = $url.(false !== strpos($url, '?') ? '&' : '?').$this->buildQuery($params);

        $this->curlit();

        return $this->response;
    }

    public function curlHeader($ch, $header)
    {
        $i = strpos($header, ':');

        if (!empty($i)) {
            $key = str_replace('-', '_', Tools::strtolower(Tools::substr($header, 0, $i)));
            $value = trim(Tools::substr($header, $i + 2));
            $this->response['headers'][$key] = $value;
        }

        return Tools::strlen($header);
    }

    private function prepareMethod($method)
    {
        $this->method = Tools::strtoupper($method);
    }

    public function buildQuery($params)
    {
        return '' != http_build_query($params) ? http_build_query($params) : '';
    }

    public function parseResponse($response, $format)
    {
        if (isset($format)) {
            switch ($format) {
                case 'html':
                    $the_response = $response;
                    break;
                case 'pdf':
                    $the_response = $response;
                    break;
                case 'json':
                    $the_response = Tools::jsonDecode($response);
                    break;
                default:
                    $the_response = simplexml_load_string($response);
                    break;
            }
        }

        return $the_response;
    }

    public function success()
    {
        return empty($this->errors);
    }

    public function getErrors()
    {
        return $this->errors;
    }
}
