* Date: 2017/9/27 * Curl multi threading */ namespace QL\Ext; use Ares333\Curl\Curl; use QL\Contracts\PluginContract; use QL\QueryList; use Closure; class CurlMulti implements PluginContract { protected $urls = []; protected $queryList; protected $successCallback; protected $curl; protected $isRunning = false; public function __construct(QueryList $queryList,$urls) { $this->urls = is_string($urls)?[$urls]:$urls; $this->queryList = $queryList; $this->curl = new Curl(); $this->curl->opt = [ CURLOPT_RETURNTRANSFER => true ]; } public static function install(QueryList $queryList, ...$opt) { $name = $opt[0] ?? 'curlMulti'; $queryList->bind($name,function ($urls = []){ return new CurlMulti($this,$urls); }); } public function getUrls() { return $this->urls; } public function add($urls) { is_string($urls) && $urls = [$urls]; $this->urls = array_merge($this->urls,$urls); //如果当前任务正在运行就实时动态添加任务 $this->isRunning && $this->addTasks($urls); return $this; } public function success(Closure $callback) { $this->successCallback = function ($r) use($callback){ $this->queryList->setHtml($r['body']); $callback($this->queryList,$this,$r); }; return $this; } public function error(Closure $callback) { $this->curl->cbFail = function ($info) use($callback){ $callback($info,$this); }; return $this; } public function start(array $opt = []) { $this->bindOpt($opt); $this->addTasks($this->urls); $this->isRunning = true; $this->curl->start(); $this->isRunning = false; $this->urls = []; return $this; } protected function bindOpt($opt) { foreach ($opt as $key => $value) { if($key == 'opt'){ $this->curl->opt = $this->arrayMerge($this->curl->opt,$value); }else { $this->curl->$key = $value; } } } protected function addTasks($urls) { foreach ($urls as $url) { $this->curl->add([ 'opt' => array( CURLOPT_URL => $url ) ],$this->successCallback); } } protected function arrayMerge($arr1,$arr2) { foreach ($arr2 as $key => $value) { $arr1[$key] = $value; } return $arr1; } }