Mercurial > hg > ywww
diff twitter/EpiCurl.php @ 6:077b0a0a3e6d
remaining originals according to dependency walk
author | Robert Boland <robert@markup.co.uk> |
---|---|
date | Thu, 16 Feb 2017 22:29:02 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/twitter/EpiCurl.php Thu Feb 16 22:29:02 2017 +0000 @@ -0,0 +1,166 @@ +<?php +class EpiCurl +{ + const timeout = 3; + static $inst = null; + static $singleton = 0; + private $mc; + private $msgs; + private $running; + private $execStatus; + private $selectStatus; + private $sleepIncrement = 1.1; + private $requests = array(); + private $responses = array(); + private $properties = array(); + + function __construct() + { + if(self::$singleton == 0) + { + throw new Exception('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = EpiCurl::getInstance();'); + } + + $this->mc = curl_multi_init(); + $this->properties = array( + 'code' => CURLINFO_HTTP_CODE, + 'time' => CURLINFO_TOTAL_TIME, + 'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD, + 'type' => CURLINFO_CONTENT_TYPE, + 'url' => CURLINFO_EFFECTIVE_URL + ); + } + + public function addCurl($ch) + { + $key = $this->getKey($ch); + $this->requests[$key] = $ch; + curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback')); + + $code = curl_multi_add_handle($this->mc, $ch); + + // (1) + if($code === CURLM_OK || $code === CURLM_CALL_MULTI_PERFORM) + { + do { + $code = $this->execStatus = curl_multi_exec($this->mc, $this->running); + } while ($this->execStatus === CURLM_CALL_MULTI_PERFORM); + + return new EpiCurlManager($key); + } + else + { + return $code; + } + } + + public function getResult($key = null) + { + if($key != null) + { + if(isset($this->responses[$key])) + { + return $this->responses[$key]; + } + + $innerSleepInt = $outerSleepInt = 1; + while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM)) + { + usleep($outerSleepInt); + $outerSleepInt = max(1, ($outerSleepInt*$this->sleepIncrement)); + $ms=curl_multi_select($this->mc, 0); + if($ms > 0) + { + do{ + $this->execStatus = curl_multi_exec($this->mc, $this->running); + usleep($innerSleepInt); + $innerSleepInt = max(1, ($innerSleepInt*$this->sleepIncrement)); + }while($this->execStatus==CURLM_CALL_MULTI_PERFORM); + $innerSleepInt = 1; + } + $this->storeResponses(); + if(isset($this->responses[$key]['data'])) + { + return $this->responses[$key]; + } + $runningCurrent = $this->running; + } + return null; + } + return false; + } + + private function getKey($ch) + { + return (string)$ch; + } + + private function headerCallback($ch, $header) + { + $_header = trim($header); + $colonPos= strpos($_header, ':'); + if($colonPos > 0) + { + $key = substr($_header, 0, $colonPos); + $val = preg_replace('/^\W+/','',substr($_header, $colonPos)); + $this->responses[$this->getKey($ch)]['headers'][$key] = $val; + } + return strlen($header); + } + + private function storeResponses() + { + while($done = curl_multi_info_read($this->mc)) + { + $key = (string)$done['handle']; + $this->responses[$key]['data'] = curl_multi_getcontent($done['handle']); + foreach($this->properties as $name => $const) + { + $this->responses[$key][$name] = curl_getinfo($done['handle'], $const); + } + curl_multi_remove_handle($this->mc, $done['handle']); + curl_close($done['handle']); + } + } + + static function getInstance() + { + if(self::$inst == null) + { + self::$singleton = 1; + self::$inst = new EpiCurl(); + } + + return self::$inst; + } +} + +class EpiCurlManager +{ + private $key; + private $epiCurl; + + function __construct($key) + { + $this->key = $key; + $this->epiCurl = EpiCurl::getInstance(); + } + + function __get($name) + { + $responses = $this->epiCurl->getResult($this->key); + return isset($responses[$name]) ? $responses[$name] : null; + } + + function __isset($name) + { + $val = self::__get($name); + return empty($val); + } +} + +/* +* Credits: +* - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success. +*/ +?>