Mercurial > hg > ywww
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 5:55445b456ad0 | 6:077b0a0a3e6d |
|---|---|
| 1 <?php | |
| 2 class EpiCurl | |
| 3 { | |
| 4 const timeout = 3; | |
| 5 static $inst = null; | |
| 6 static $singleton = 0; | |
| 7 private $mc; | |
| 8 private $msgs; | |
| 9 private $running; | |
| 10 private $execStatus; | |
| 11 private $selectStatus; | |
| 12 private $sleepIncrement = 1.1; | |
| 13 private $requests = array(); | |
| 14 private $responses = array(); | |
| 15 private $properties = array(); | |
| 16 | |
| 17 function __construct() | |
| 18 { | |
| 19 if(self::$singleton == 0) | |
| 20 { | |
| 21 throw new Exception('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = EpiCurl::getInstance();'); | |
| 22 } | |
| 23 | |
| 24 $this->mc = curl_multi_init(); | |
| 25 $this->properties = array( | |
| 26 'code' => CURLINFO_HTTP_CODE, | |
| 27 'time' => CURLINFO_TOTAL_TIME, | |
| 28 'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD, | |
| 29 'type' => CURLINFO_CONTENT_TYPE, | |
| 30 'url' => CURLINFO_EFFECTIVE_URL | |
| 31 ); | |
| 32 } | |
| 33 | |
| 34 public function addCurl($ch) | |
| 35 { | |
| 36 $key = $this->getKey($ch); | |
| 37 $this->requests[$key] = $ch; | |
| 38 curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback')); | |
| 39 | |
| 40 $code = curl_multi_add_handle($this->mc, $ch); | |
| 41 | |
| 42 // (1) | |
| 43 if($code === CURLM_OK || $code === CURLM_CALL_MULTI_PERFORM) | |
| 44 { | |
| 45 do { | |
| 46 $code = $this->execStatus = curl_multi_exec($this->mc, $this->running); | |
| 47 } while ($this->execStatus === CURLM_CALL_MULTI_PERFORM); | |
| 48 | |
| 49 return new EpiCurlManager($key); | |
| 50 } | |
| 51 else | |
| 52 { | |
| 53 return $code; | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 public function getResult($key = null) | |
| 58 { | |
| 59 if($key != null) | |
| 60 { | |
| 61 if(isset($this->responses[$key])) | |
| 62 { | |
| 63 return $this->responses[$key]; | |
| 64 } | |
| 65 | |
| 66 $innerSleepInt = $outerSleepInt = 1; | |
| 67 while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM)) | |
| 68 { | |
| 69 usleep($outerSleepInt); | |
| 70 $outerSleepInt = max(1, ($outerSleepInt*$this->sleepIncrement)); | |
| 71 $ms=curl_multi_select($this->mc, 0); | |
| 72 if($ms > 0) | |
| 73 { | |
| 74 do{ | |
| 75 $this->execStatus = curl_multi_exec($this->mc, $this->running); | |
| 76 usleep($innerSleepInt); | |
| 77 $innerSleepInt = max(1, ($innerSleepInt*$this->sleepIncrement)); | |
| 78 }while($this->execStatus==CURLM_CALL_MULTI_PERFORM); | |
| 79 $innerSleepInt = 1; | |
| 80 } | |
| 81 $this->storeResponses(); | |
| 82 if(isset($this->responses[$key]['data'])) | |
| 83 { | |
| 84 return $this->responses[$key]; | |
| 85 } | |
| 86 $runningCurrent = $this->running; | |
| 87 } | |
| 88 return null; | |
| 89 } | |
| 90 return false; | |
| 91 } | |
| 92 | |
| 93 private function getKey($ch) | |
| 94 { | |
| 95 return (string)$ch; | |
| 96 } | |
| 97 | |
| 98 private function headerCallback($ch, $header) | |
| 99 { | |
| 100 $_header = trim($header); | |
| 101 $colonPos= strpos($_header, ':'); | |
| 102 if($colonPos > 0) | |
| 103 { | |
| 104 $key = substr($_header, 0, $colonPos); | |
| 105 $val = preg_replace('/^\W+/','',substr($_header, $colonPos)); | |
| 106 $this->responses[$this->getKey($ch)]['headers'][$key] = $val; | |
| 107 } | |
| 108 return strlen($header); | |
| 109 } | |
| 110 | |
| 111 private function storeResponses() | |
| 112 { | |
| 113 while($done = curl_multi_info_read($this->mc)) | |
| 114 { | |
| 115 $key = (string)$done['handle']; | |
| 116 $this->responses[$key]['data'] = curl_multi_getcontent($done['handle']); | |
| 117 foreach($this->properties as $name => $const) | |
| 118 { | |
| 119 $this->responses[$key][$name] = curl_getinfo($done['handle'], $const); | |
| 120 } | |
| 121 curl_multi_remove_handle($this->mc, $done['handle']); | |
| 122 curl_close($done['handle']); | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 static function getInstance() | |
| 127 { | |
| 128 if(self::$inst == null) | |
| 129 { | |
| 130 self::$singleton = 1; | |
| 131 self::$inst = new EpiCurl(); | |
| 132 } | |
| 133 | |
| 134 return self::$inst; | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 class EpiCurlManager | |
| 139 { | |
| 140 private $key; | |
| 141 private $epiCurl; | |
| 142 | |
| 143 function __construct($key) | |
| 144 { | |
| 145 $this->key = $key; | |
| 146 $this->epiCurl = EpiCurl::getInstance(); | |
| 147 } | |
| 148 | |
| 149 function __get($name) | |
| 150 { | |
| 151 $responses = $this->epiCurl->getResult($this->key); | |
| 152 return isset($responses[$name]) ? $responses[$name] : null; | |
| 153 } | |
| 154 | |
| 155 function __isset($name) | |
| 156 { | |
| 157 $val = self::__get($name); | |
| 158 return empty($val); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 /* | |
| 163 * Credits: | |
| 164 * - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success. | |
| 165 */ | |
| 166 ?> |
