public function start() { if ($this->isActive || $this->isStopped) { return; } $this->isActive = true; $this->isStarted = true; $curlHandle = curl_multi_init(); try { do { // send requests from queue to CURL if (count($this->activeRequests) < $this->connectionsLimit) { for ($i = $this->connectionsLimit - count($this->activeRequests); $i > 0; $i--) { $request = $this->queue->pop(); if ($request) { $this->sendRequestToMultiCurl($curlHandle, $request); $this->activeRequests[$request->getId()] = $request; } else { break; } } } while (CURLM_CALL_MULTI_PERFORM === curl_multi_exec($curlHandle, $activeThreads)) { } // check complete requests curl_multi_select($curlHandle, $this->requestingDelay); while ($completeCurlInfo = curl_multi_info_read($curlHandle)) { $completeRequestId = Request::getRequestIdByCurlHandle($completeCurlInfo['handle']); $completeRequest = $this->activeRequests[$completeRequestId]; unset($this->activeRequests[$completeRequestId]); curl_multi_remove_handle($curlHandle, $completeRequest->getCurlHandle()); $completeRequest->handleCurlResult(); // check if response code is 301 or 302 and follow location $ignoreNotification = false; $completeRequestCode = $completeRequest->getCode(); if ($completeRequestCode == 301 || $completeRequestCode == 302) { $completeRequestOptions = $completeRequest->getCurlOptions(); if (!empty($completeRequestOptions[CURLOPT_FOLLOWLOCATION])) { $completeRequest->_permanentlyMoved = empty($completeRequest->_permanentlyMoved) ? 1 : $completeRequest->_permanentlyMoved + 1; $responseHeaders = $completeRequest->getResponseHeaders(true); if ($completeRequest->_permanentlyMoved < 5 && !empty($responseHeaders['Location'])) { // figure out whether we're dealing with an absolute or relative redirect (thanks to kmontag https://github.com/kmontag for this bugfix) $redirectedUrl = (parse_url($responseHeaders['Location'], PHP_URL_SCHEME) === null ? $completeRequest->getBaseUrl() : '') . $responseHeaders['Location']; $completeRequest->setUrl($redirectedUrl); $completeRequest->reInitCurlHandle(); $this->pushRequestToQueue($completeRequest); $ignoreNotification = true; } } } if (!$ignoreNotification) { $this->notifyRequestComplete($completeRequest); } } } while (!$this->isStopped && ($this->activeRequests || $this->queue->count())); } catch (Exception $exception) { } $this->isActive = false; if ($curlHandle && is_resource($curlHandle)) { curl_multi_close($curlHandle); } if (!empty($exception)) { throw $exception; } /** @noinspection PhpUndefinedMethodInspection */ $this->callbacks->onComplete($this); }
/** * {@inheritdoc} */ public function count() { return $this->exceptional(function () { return $this->queue->count(); }); }
/** * {@inheritdoc} */ public function count() { return $this->queue->count(); }