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 ?>