Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/modules/ipol.sdek/classes/lib/Api/Client/
Upload File :
Current File : /var/www/homesaver/www/bitrix/modules/ipol.sdek/classes/lib/Api/Client/curl.php

<?php
namespace Ipolh\SDEK\Api\Client;

use Exception;

/**
 * Class curl
 * @package Ipolh\SDEK\Api\Client
 */
class curl
{
    /**
     * cURL handle
     * @var null|resource
     */
    private $client;

    /**
     * @var mixed
     */
    private $answer;

    /**
     * @var null|int
     */
    private $code;

    /**
     * @var string
     */
    private $url = '';

    /**
     * @var array
     */
    private $config = [];

    /**
     * @var int
     */
    private $curlErrNum = 0;

    /**
     * @var array
     */
    private $arrResponseHeaders = [];

    /**
     * curl constructor.
     * @param string $url
     * @param array $config
     * @throws Exception
     */
    public function __construct($url = false, array $config = [])
    {
        if (!function_exists('curl_init')) {
            throw new Exception('No CURL library');
        }
        $this->client = curl_init();
        if ($url) {
            $this->setUrl($url);
        }
        if ($config) {
            $this->config($config);
        }
    }

    /**
     * @param string $data
     * @return $this
     */
    public function post($data = '')
    {
        $this->setOpt(CURLOPT_POST, TRUE);
        if($data) {
            $this->setOpt(CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($this->client, CURLOPT_HEADERFUNCTION, [$this, 'responseHeaderParser']);
        $this->request();
        return $this;
    }

    /**
     * @param array $data
     * @return $this
     */
    public function get(array $data = [])
    {
        if ($data) {
            if (strpos($this->url, '?') !== false) {
                $this->url = substr($this->url, 0, strpos($this->url, '?'));
            }
            $this->url .= '?' . http_build_query($data);
        }
        $this->request();

        return $this;
    }

    /**
     * @param string $data
     * @return $this
     */
    public function put($data = '')
    {
        curl_setopt($this->client,CURLOPT_CUSTOMREQUEST, 'PUT');
        if($data) {
            $this->setOpt(CURLOPT_POSTFIELDS, $data);
        }
        $this->request();

        return $this;
    }

    /**
     * @return $this
     */
    public function delete()
    {
        $this->setOpt(CURLOPT_CUSTOMREQUEST, "DELETE");

        $this->request();

        return $this;
    }

    /**
     * @param array $args
     * @return $this
     */
    public function config(array $args)
    {
        $this->config = $args;
        curl_setopt_array($this->client, $args);

        return $this;
    }

    /**
     * @param int $opt
     * @param mixed $val
     * @return $this
     */
    public function setOpt($opt, $val)
    {
        curl_setopt($this->client, $opt, $val);

        return $this;
    }

    /**
     * @return int|null
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * @return mixed
     */
    public function getAnswer()
    {
        return $this->answer;
    }

    /**
     * @return array
     */
    public function getRequest()
    {
        return array('code' => $this->getCode(), 'answer' => $this->getAnswer());
    }

    /**
     * @param string $url
     * @return $this
     */
    public function setUrl($url)
    {
        $this->url = $url;
        return $this;
    }

    /**
     * @return string
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * @return $this
     */
    public function flee()
    {
        if ($this->client) {
            curl_close($this->client);
        }
        return $this;
    }

    /**
     * @param bool $close
     * @return $this
     */
    private function request($close = true)
    {
        $this->setOpt(CURLOPT_URL, $this->url);
        $this->answer = curl_exec($this->client);
        $this->code = curl_getinfo($this->client, CURLINFO_HTTP_CODE);
        if ($this->code === 0) {
            $this->curlErrNum = curl_errno($this->client);
        }
        if ($close) {
            $this->flee();
        }
        return $this;
    }

    /**
     * @param array $data
     * @return $this
     */
    public function getMulti(array $data)
    {
        $curlHandles = [];
        $codes       = [];
        $results     = [];

        if (!is_array($data)) {
            throw new Exception('Unknown data type given for cURL multi GET request');
        }

        $nodes = count($data);
        if ($nodes < 1) {
            throw new Exception('Empty data array given for cURL multi GET request');
        }

        $curlMulti = curl_multi_init();

        for ($i = 0; $i < $nodes; $i++) {
            $url = $this->url.(empty($data[$i]) ? '' : '?'.http_build_query($data[$i]));

            $curlHandles[$i] = curl_init($url);

            if (!empty($this->config)) {
                curl_setopt_array($curlHandles[$i], $this->config);
            }
            curl_setopt($curlHandles[$i], CURLOPT_URL, $url);
            curl_setopt($curlHandles[$i], CURLOPT_RETURNTRANSFER, true);
            if (!empty($data[$i])) {
                $results[$i]['request'] = $data[$i];
            }

            curl_multi_add_handle($curlMulti, $curlHandles[$i]);
        }

        $running = null;
        do {
            curl_multi_exec($curlMulti, $running);
            /*
            $i = 0;
            while (false !== ($info = curl_multi_info_read($curlMulti))) {
                $codes[$i] = curl_getinfo($info['handle'], CURLINFO_HTTP_CODE);
                $i++;
            }
            */
        } while ($running);

        for ($i = 0; $i < $nodes; $i++) {
            $results[$i]['response'] = curl_multi_getcontent($curlHandles[$i]);
            $results[$i]['code']     = curl_getinfo($curlHandles[$i], CURLINFO_HTTP_CODE);
            curl_multi_remove_handle($curlMulti, $curlHandles[$i]);

            $codes[] = $results[$i]['code'];
        }
        curl_multi_close($curlMulti);

        $this->answer = $results;

        // HTTP status magic crutches
        $codes = array_unique($codes);
        if (in_array('200', $codes)) {
            // At least one request successful
            $this->code = 200;
        } else {
            // Returns da lower existing HTTP status
            sort($codes);
            $this->code = $codes[0];
        }

        return $this;
    }

    /**
     * @param array $data
     * @return $this
     */
    public function postMulti(array $data)
    {
        $curlHandles = [];
        $codes       = [];
        $results     = [];

        if (!is_array($data)) {
            throw new Exception('Unknown data type given for cURL multi POST request');
        }

        $nodes = count($data);
        if ($nodes < 1) {
            throw new Exception('Empty data array given for cURL multi POST request');
        }

        $curlMulti = curl_multi_init();

        for ($i = 0; $i < $nodes; $i++) {
            $curlHandles[$i] = curl_init($this->url);

            if (!empty($this->config)) {
                curl_setopt_array($curlHandles[$i], $this->config);
            }
            curl_setopt($curlHandles[$i], CURLOPT_URL, $this->url);
            curl_setopt($curlHandles[$i], CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curlHandles[$i], CURLOPT_POST, true);
            if (!empty($data[$i])) {
                $json = json_encode($data[$i], JSON_UNESCAPED_UNICODE);
                curl_setopt($curlHandles[$i], CURLOPT_POSTFIELDS, $json);
                $results[$i]['request'] = $json;
            }

            curl_multi_add_handle($curlMulti, $curlHandles[$i]);
        }

        $running = null;
        do {
            curl_multi_exec($curlMulti, $running);
            /*
            $i = 0;
            while (false !== ($info = curl_multi_info_read($curlMulti))) {
                $codes[$i] = curl_getinfo($info['handle'], CURLINFO_HTTP_CODE);
                $i++;
            }
            */
        } while ($running);

        for ($i = 0; $i < $nodes; $i++) {
            $results[$i]['response'] = curl_multi_getcontent($curlHandles[$i]);
            $results[$i]['code']     = curl_getinfo($curlHandles[$i], CURLINFO_HTTP_CODE);
            curl_multi_remove_handle($curlMulti, $curlHandles[$i]);

            $codes[] = $results[$i]['code'];
        }
        curl_multi_close($curlMulti);

        $this->answer = $results;

        // HTTP status magic crutches
        $codes = array_unique($codes);
        if (in_array('200', $codes)) {
            // At least one request successful
            $this->code = 200;
        } else {
            // Returns da lower existing HTTP status
            sort($codes);
            $this->code = $codes[0];
        }

        return $this;
    }

    private function responseHeaderParser($curl, $header)
    {// this function is called by curl for each header received
        $len = strlen($header);
        $header = explode(':', $header, 2);
        if (count($header) < 2) { // ignore invalid headers
            return $len;
        }

        $this->arrResponseHeaders[strtolower(trim($header[0]))][] = trim($header[1]);
        return $len;
    }

    /**
     * @return int
     */
    public function getCurlErrNum()
    {
        return $this->curlErrNum;
    }

    /**
     * @return array
     */
    public function getArrResponseHeaders()
    {
        return $this->arrResponseHeaders;
    }
}