phalconplus Documentation v1.3.0-development
Class
Class PhalconPlus Curl

# Curl

        namespace PhalconPlus\Curl;
    use PhalconPlus\Curl\Request;
    use PhalconPlus\Curl\Response;
    use PhalconPlus\Curl\Exception as CurlException;
    use Phalcon\Text;

    /**
    * @ref https://github.com/anlutro/php-curl
    */
    class Curl
    {
        /**
         * The cURL resource.
         */
        protected ch = null;
        /**
         * The default headers.
         *
         * @var array
         */
        protected defaultHeaders = [];
        /**
         * The default curl options.
         *
         * @var array
         */
        protected defaultOptions = [];

        /**
         * The base url
         *
         * @var string
         */
        protected baseUrl = "";

        public function __construct(array opts = [])
        {
            let this->defaultOptions = opts;
        }

        /**
         * Get allowed methods.
         *
         * @return array
         */
        public function getAllowedMethods() -> array
        {
            return Request::methods;
        }
        /**
         * Set the default headers for every request.
         *
         * @param array $headers
         */
        public function setDefaultHeaders(array headers) ->
        {
            let this->defaultHeaders = headers;
            return this;
        }
        /**
         * Get the default headers.
         *
         * @return array
         */
        public function getDefaultHeaders() -> array
        {
            return this->defaultHeaders;
        }
        /**
         * Set the default curl options for every request.
         *
         * @param array $options
         */
        public function setDefaultOptions(array options) ->
        {
            let this->defaultOptions = options + this->defaultOptions;
            return this;
        }
        /**
         * Get the default options.
         *
         * @return array
         */
        public function getDefaultOptions()
        {
            return this->defaultOptions;
        }

        /**
         * Get the default options.
         *
         * @return array
         */
        public function setBaseUrl(string baseUrl) ->
        {
            if Text::startsWith(baseUrl, "http://") || Text::startsWith(baseUrl, "https://") {
                //
            } else {
                throw new CurlException("Base Url should start with http:// or https://");
            }
            let this->baseUrl = baseUrl;
            return this;
        }

        /**
         * Build an URL with an optional query string.
         *
         * @param  string $url   the base URL without any query string
         * @param  array  $query array of GET parameters
         *
         * @return string
         */
        public function buildUrl(string url, array query) -> string
        {
            if Text::startsWith(url, "http://") || Text::startsWith(url, "https://") {
                //
            } else {
                let url = this->baseUrl . url;
            }

            if (empty(query)) {
                return url;
            }
            var retUrl;
            var parts = parse_url(url);
            var queryString = "";
            if (isset(parts["query"]) && parts["query"]) {
                let queryString = queryString . parts["query"]."&".http_build_query(query);
            } else {
                let queryString = queryString . http_build_query(query);
            }

            let retUrl = parts["scheme"]."://".parts["host"];
            if (isset(parts["port"])) {
                let retUrl = retUrl . ":" . parts["port"];
            }
            if (isset(parts["path"])) {
                let retUrl = retUrl . parts["path"];
            }
            if (queryString) {
                let retUrl = retUrl . "?" . queryString;
            }
            return retUrl;
        }
        /**
         * Create a new response object and set its values.
         *
         * @param  string  $method    get, post, etc
         * @param  string  $url
         * @param  mixed   $data      POST data
         * @param  int     $encoding  Request::ENCODING_* constant specifying how to process the POST data
         *
         * @return Request
         */
        public function newRequest(string method, string url, var data, int encoding = Request::ENCODING_QUERY) ->
        {
            var request;
            let request = new Request(this);
            if (this->defaultHeaders) {
                request->setHeaders(this->defaultHeaders);
            }
            if (this->defaultOptions) {
                request->setOptions(this->defaultOptions);
            }
            request->setMethod(method);
            if Text::startsWith(url, "http://") || Text::startsWith(url, "https://") {
                //
            } else {
                let url = this->baseUrl . url;
            }
            request->setUrl(url);
            request->setData(data);
            request->setEncoding(encoding);
            return request;
        }
        /**
         * Create a new JSON request and set its values.
         *
         * @param  string $method  get, post etc
         * @param  string $url
         * @param  mixed  $data    POST data
         *
         * @return Request
         */
        public function newJsonRequest(string method, string url, array data = []) ->
        {
            return this->newRequest(method, url, data, Request::ENCODING_JSON);
        }
        /**
         * Create a new raw request and set its values.
         *
         * @param  string $method  get, post etc
         * @param  string $url
         * @param  mixed  $data    request body
         *
         * @return Request
         */
        public function newRawRequest(string method, string url, var data = "") ->
        {
            return this->newRequest(method, url, data, Request::ENCODING_RAW);
        }
        /**
         * Prepare the curl resource for sending a request.
         *
         * @param  Request $request
         *
         * @return Curl
         */
        public function prepareRequest( request) ->
        {
            let this->ch = curl_init();
            curl_setopt(this->ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt(this->ch, CURLOPT_HEADER, true);
            var auth, options, method;
            let auth = request->getUserAndPass();
            if (auth) {
                curl_setopt(this->ch, CURLOPT_USERPWD, auth);
            }
            curl_setopt(this->ch, CURLOPT_URL, request->getUrl());
            let options = request->getOptions();
            if (!empty(options)) {
                curl_setopt_array(this->ch, options);
            }
            let method = request->getMethod();
            curl_setopt(this->ch, CURLOPT_CUSTOMREQUEST, strtoupper(method));
            curl_setopt(this->ch, CURLOPT_HTTPHEADER, request->formatHeaders());
            if (request->hasData()) {
                curl_setopt(this->ch, CURLOPT_POSTFIELDS, request->encodeData());
            }
            if ($method === "head") {
                curl_setopt(this->ch, CURLOPT_NOBODY, true);
            }
            return this;
        }
        /**
         * Send a request.
         *
         * @param  Request $request
         *
         * @return Response
         */
        public function sendRequest( request) ->
        {
            this->prepareRequest(request);
            var result, response;
            let result = curl_exec(this->ch);
            if (result === false) {
                var ex, errno, msg, errmsg;
                let errno = curl_errno(this->ch);
                let errmsg = curl_error(this->ch);
                let msg = "Curl request failed with error [".errno.":". errmsg;
                curl_close(this->ch);
                throw new CurlException([msg, [request]], errno);
            }
            let response = this->createResponseObject(result);
            curl_close(this->ch);
            return response;
        }
        /**
        * Extract the response info, header and body from a cURL response. Saves
        * the data in variables stored on the object.
        *
        * @param  string $response
        *
        * @return Response
        */
        protected function createResponseObject(response) ->
        {
            var info, headerSize, headers, body;
            let info = curl_getinfo(this->ch);
            let headerSize = curl_getinfo(this->ch, CURLINFO_HEADER_SIZE);
            let headers = substr(response, 0, headerSize);
            let body = substr(response, headerSize);
            return new Response(body, headers, info);
        }
        /**
        * Handle dynamic calls to the class.
        *
        * @param  string $func
        * @param  array  $args
        *
        * @return Response
        */
        public function __call(string func, array args) ->
        {
            var request, method, encoding, url, data = null, msg = "";
            let method = strtolower(func);
            let encoding = Request::ENCODING_QUERY;
            if (substr(method, 0, 4) === "json") {
                let encoding = Request::ENCODING_JSON;
                let method = substr(method, 4);
            } elseif (substr(method, 0, 3) === "raw") {
                let encoding = Request::ENCODING_RAW;
                let method = substr(method, 3);
            }
            if (!array_key_exists(method, Request::methods)) {
                let msg = "Method [".method."] not a valid HTTP method.";
                throw new \BadMethodCallException(msg);
            }
            if !isset(args[0]) {
                let msg = "Missing argument 1 (".url.") for ".__CLASS__. "::" . func;
                throw new \BadMethodCallException(msg);
            }
            let url = args[0];
            if isset(args[1]) {
                let data = args[1];
            }

    		// new Request
            let request = this->newRequest(method, url, data, encoding);
    		// set Header
    		if isset(args[2]) {
    			if typeof args[2] == "string" {
    				request->setHeader(args[2]);
    			} elseif typeof args[2] == "array" {
    				var k, v;
    		    	for k, v in args[2] {
    					request->setHeader(k, v, true);
    				}
    			}
    		}
            return this->sendRequest(request);
        }
    }