Location: PHPKode > scripts > MultiRequest > MultiRequest/Request.php
<?php

/**
 * @see http://code.google.com/p/multirequest
 * @author Barbushin Sergey http://www.linkedin.com/in/barbushin
 *
 */
class MultiRequest_Request {
	
	/**
	 * @var MultiRequest_Callbacks
	 */
	protected $callbacks;
	
	protected $url;
	protected $realUrl;
	protected $curlHandle;
	protected $headers = array('Expect:');
	protected $getData;
	protected $postData;
	protected $curlOptions = array(CURLOPT_TIMEOUT => 3600, CURLOPT_CONNECTTIMEOUT => 200, CURLOPT_FAILONERROR => true, CURLOPT_FRESH_CONNECT => true, CURLOPT_HEADER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_MAXREDIRS => 10, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false, CURLOPT_FORBID_REUSE => true, CURLOPT_VERBOSE => true, CURLOPT_MAXCONNECTS => 1);
	protected $curlInfo;
	protected $serverEncoding = 'utf-8';
	protected $defaultClientEncoding = 'utf-8';
	protected $responseHeaders;
	protected $responseHeadersList = array();
	protected $responseContent;
	protected $error;
	
	protected static $clientsEncodings;

	public function __construct($url) {
		$this->callbacks = new MultiRequest_Callbacks();
		$this->url = $url;
		$this->setUrl($url);
	}

	public function setUrl($url) {
		$this->setCurlOption(CURLOPT_URL, $url);
	}

	public function getDomain() {
		return parse_url($this->url, PHP_URL_HOST);
	}

	public function getBaseUrl() {
		return parse_url($this->url, PHP_URL_SCHEME) . '://' . $this->getDomain();
	}

	public function getRealUrl() {
		return $this->realUrl;
	}

	public function setEncoding($charset) {
		$this->charsetg = $charset;
	}

	public function addHeader($header) {
		$this->headers[] = $header;
	}

	public function addHeaders($headers) {
		$this->headers = array_merge($this->headers, $headers);
	}

	public function setGetData($getData) {
		$this->getData = $getData;
	}

	public function setPostData($postData) {
		$this->postData = $postData;
	}

	public function getPostData() {
		return $this->postData;
	}

	public function setPostVar($var, $value) {
		$this->postData[$var] = $value;
	}

	public function setCurlOption($optionName, $value) {
		if($optionName == CURLOPT_URL) {
			$this->realUrl = $value;
		}
		$this->curlOptions[$optionName] = $value;
	}

	public function getCurlOptions() {
		return $this->curlOptions;
	}

	public function addCurlOptions(array $options) {
		foreach($options as $option => $value) {
			$this->curlOptions[$option] = $value;
		}
	}

	public function setCookiesStorage($filepath) {
		$this->curlOptions[CURLOPT_COOKIEJAR] = $filepath;
		$this->curlOptions[CURLOPT_COOKIEFILE] = $filepath;
	}

	protected function initCurlHandle() {
		$curlHandle = curl_init($this->url);
		$curlOptions = $this->curlOptions;
		$curlOptions[CURLINFO_HEADER_OUT] = true;
		
		if($this->headers) {
			$curlOptions[CURLOPT_HTTPHEADER] = $this->headers;
		}
		if($this->postData) {
			$postData = $this->postData;
			
			$clientEncoding = isset(self::$clientsEncodings[$this->getDomain()]) ? self::$clientsEncodings[$this->getDomain()] : $this->defaultClientEncoding;
			if($clientEncoding != $this->serverEncoding) {
				array_walk_recursive($postData, create_function('&$value', '$value = mb_convert_encoding($value, "' . $clientEncoding . '", "' . $this->serverEncoding . '");'));
			}
			$curlOptions[CURLOPT_POST] = true;
			$curlOptions[CURLOPT_POSTFIELDS] = $postData;
			$this->addHeader('Content-Type:	application/x-www-form-urlencoded; charset=' . $clientEncoding);
		}
		
		curl_setopt_array($curlHandle, $curlOptions);
		return $curlHandle;
	}

	protected function detectClientCharset($headers) {
		if(isset($this->curlInfo['content_type']) && preg_match('/charset\s*=\s*([\w\-\d]+)/i', $this->curlInfo['content_type'], $m)) {
			return strtolower($m[1]);
		}
		return $this->defaultClientEncoding;
	}

	public function getId() {
		return self::getRequestIdByCurlHandle($this->curlHandle);
	}

	public static function getRequestIdByCurlHandle($curlHandle) {
		return substr((string) $curlHandle, 13);
	}

	public function getUrl() {
		return $this->url . ($this->getData ? (strstr($this->url, '?') === false ? '?' : '&') . http_build_query($this->getData) : '');
	}

	public function getCurlHandle() {
		if(!$this->curlHandle) {
			$this->reinitCurlHandle();
		}
		return $this->curlHandle;
	}

	public function reinitCurlHandle() {
		$this->curlHandle = $this->initCurlHandle();
	}

	public function getTime() {
		return $this->curlInfo['total_time'];
	}

	public function getCode() {
		return $this->curlInfo['http_code'];
	}

	public function initResponseDataFromHandler(MultiRequest_Handler $handler) {
		$curlHandle = $this->getCurlHandle();
		$this->curlInfo = curl_getinfo($curlHandle);
		$this->error = curl_error($curlHandle);
		$responseData = curl_multi_getcontent($curlHandle);
		
		$this->responseHeaders = substr($responseData, 0, curl_getinfo($curlHandle, CURLINFO_HEADER_SIZE));
		$this->responseContent = substr($responseData, curl_getinfo($curlHandle, CURLINFO_HEADER_SIZE));
		$clientEncoding = $this->detectClientCharset($this->getResponseHeaders());
		if($clientEncoding && $clientEncoding != $this->serverEncoding) {
			self::$clientsEncodings[$this->getDomain()] = $clientEncoding;
			$this->responseContent = mb_convert_encoding($this->responseContent, $this->serverEncoding, $clientEncoding);
		}
		if($curlHandle && is_resource($curlHandle)) {
			curl_close($curlHandle);
		}
	}

	public function notifyIsComplete(MultiRequest_Handler $handler) {
		$this->callbacks->onComplete($this, $handler);
		
		$failException = $this->getFailException();
		if($failException) {
			$this->notifyIsFailed($failException, $handler);
		}
		else {
			$this->notifyIsSuccess($handler);
		}
	}

	public function onComplete($callback) {
		$this->callbacks->add(__FUNCTION__, $callback);
		return $this;
	}

	public function onFailed($callback) {
		$this->callbacks->add(__FUNCTION__, $callback);
		return $this;
	}

	public function onSuccess($callback) {
		$this->callbacks->add(__FUNCTION__, $callback);
		return $this;
	}

	public function notifyIsSuccess(MultiRequest_Handler $handler) {
		$this->callbacks->onSuccess($this, $handler);
	}

	public function notifyIsFailed(MultiRequest_Exception $exception, MultiRequest_Handler $handler) {
		$this->callbacks->onFailed($this, $exception, $handler);
	}

	public function getFailException() {
		if($this->error) {
			return new MultiRequest_FailedResponse('Response failed with error: ' . $this->error);
		}
		else {
			$responseCode = $this->getCode();
			$successCodes = array(200, 204);
			if(!in_array($responseCode, $successCodes)) {
				return new MultiRequest_FailedResponse('Response failed with code "' . $responseCode . '"');
			}
		}
	}

	public function getCurlInfo() {
		return $this->curlInfo;
	}

	protected function parseHeaders($headersString, $associative = false) {
		$headers = array();
		preg_match_all('/\n\s*((.*?)\s*\:\s*(.*?))[\r\n]/', $headersString, $m);
		foreach($m[1] as $i => $header) {
			if($associative) {
				$headers[$m[2][$i]] = $m[3][$i];
			}
			else {
				$headers[] = $header;
			}
		}
		return $headers;
	}

	public function getRespopnseCookies(&$deleted = null) {
		$cookies = array();
		$deleted = array();
		foreach($this->getResponseHeaders() as $header) {
			if(preg_match('/^Set-Cookie:\s*(.*?)=(.*?);/i', $header, $m)) {
				if($m[2] == 'deleted') {
					$deleted[] = $m[1];
				}
				else {
					$cookies[$m[1]] = $m[2];
				}
			}
		}
		return $cookies;
	}

	public function getRequestHeaders() {
		return isset($this->curlInfo['request_header']) ? $this->parseHeaders($this->curlInfo['request_header']) : $this->parseHeaders(implode("\n", $this->headers));
	}

	public function getResponseHeaders($assoc = false) {
		return $this->parseHeaders($this->responseHeaders, $assoc);
	}

	public function getContent() {
		return $this->responseContent;
	}
}

class MultiRequest_Exception extends Exception {
}

class MultiRequest_FailedConnection extends MultiRequest_Exception {
}

class MultiRequest_FailedResponse extends MultiRequest_Exception {
}

Return current item: MultiRequest