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.
+*/
+?>