diff --git a/.travis.yml b/.travis.yml index bdc7788..ffeca6b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ language: php php: - - 5.5 - - 5.4 + - '7.1' install: - - composer self-update - composer install \ No newline at end of file diff --git a/README.md b/README.md index e8f6945..53174bf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Travis](https://img.shields.io/travis/stil/curl-easy.svg)](https://travis-ci.org/stil/curl-easy) [![Latest Stable Version](https://poser.pugx.org/stil/curl-easy/v/stable)](https://packagist.org/packages/stil/curl-easy) [![Total Downloads](https://poser.pugx.org/stil/curl-easy/downloads)](https://packagist.org/packages/stil/curl-easy) [![License](https://poser.pugx.org/stil/curl-easy/license)](https://packagist.org/packages/stil/curl-easy) # Table of contents @@ -39,15 +40,10 @@ If you need high speed crawling in your project, you might be interested in stil ## Installation In order to use cURL-PHP library you need to install the ยป libcurl package. -It also requires PHP 5.3 or newer and Symfony's EventDispatcher 2.1.* or newer. -[Composer](http://getcomposer.org) is recommended for installation. -```json -{ - "require": { - "stil/curl-easy": "*" - } -} +Install this library as [Composer](http://getcomposer.org) package with following command: +```bash +composer require stil/curl-easy ``` ## Examples ### Single request with blocking diff --git a/composer.json b/composer.json index 63205eb..43182d7 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,10 @@ "description": "cURL wrapper for PHP. Supports parallel and non-blocking requests. For high speed crawling, see stil/curl-robot.", "license": "MIT", "require": { - "symfony/event-dispatcher": "^3.0" + "symfony/event-dispatcher": "^3.2" }, "require-dev": { - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^6.1" }, "autoload": { "psr-4": { diff --git a/src/Collection.php b/src/Collection.php index 18e6625..c0f878f 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -1,4 +1,5 @@ data; } - + /** * Sets value * - * @param mixed $key Key + * @param mixed $key Key * @param mixed $value Value * @return self */ @@ -36,7 +37,7 @@ public function set($key, $value = null) } return $this; } - + /** * Checks if key does exist * @@ -47,7 +48,7 @@ public function has($key) { return isset($this->data[$key]); } - + /** * Returns value of $key * @@ -63,7 +64,7 @@ public function get($key) throw new Exception('Key does not exist.'); } } - + /** * Removes key * diff --git a/src/ConstantsTable.php b/src/ConstantsTable.php index 2f17ba7..4a73192 100644 --- a/src/ConstantsTable.php +++ b/src/ConstantsTable.php @@ -1,4 +1,5 @@ data)) { curl_setopt_array($request->getHandle(), $this->data); } - + return $this; } - + /** * Intelligent setters * diff --git a/src/Request.php b/src/Request.php index 199ebfa..687eca0 100644 --- a/src/Request.php +++ b/src/Request.php @@ -1,4 +1,5 @@ ch = curl_init(); } - + /** * Closes cURL resource and frees the memory. * It is neccessary when you make a lot of requests @@ -44,7 +45,7 @@ public function __destruct() curl_close($this->ch); } } - + /** * Get the cURL\Options instance * Creates empty one if does not exist @@ -58,10 +59,10 @@ public function getOptions() } return $this->options; } - + /** * Sets Options - * + * * @param Options $options Options * @return void */ @@ -69,17 +70,17 @@ public function setOptions(Options $options) { $this->options = $options; } - + /** * Returns cURL raw resource - * + * * @return resource cURL handle */ public function getHandle() { return $this->ch; } - + /** * Get unique id of cURL handle * Useful for debugging or logging. @@ -90,7 +91,7 @@ public function getUID() { return (int)$this->ch; } - + /** * Perform a cURL session. * Equivalent to curl_exec(). @@ -107,7 +108,7 @@ public function send() $this->options->applyTo($this); } $content = curl_exec($this->ch); - + $response = new Response($this, $content); $errorCode = curl_errno($this->ch); if ($errorCode !== CURLE_OK) { diff --git a/src/RequestInterface.php b/src/RequestInterface.php index 88b1d4e..7581280 100644 --- a/src/RequestInterface.php +++ b/src/RequestInterface.php @@ -1,12 +1,18 @@ mh = curl_multi_init(); } - + /** * Destructor, closes curl_multi handler * @@ -44,7 +45,7 @@ public function __destruct() curl_multi_close($this->mh); } } - + /** * Returns cURL\Options object with default request's options * @@ -57,7 +58,7 @@ public function getDefaultOptions() } return $this->defaultOptions; } - + /** * Overrides default options with given Options object * @@ -68,7 +69,7 @@ public function setDefaultOptions(Options $defaultOptions) { $this->defaultOptions = $defaultOptions; } - + /** * Get cURL multi handle * @@ -78,7 +79,7 @@ public function getHandle() { return $this->mh; } - + /** * Attach request to queue. * @@ -90,7 +91,7 @@ public function attach(Request $request) $this->queue[$request->getUID()] = $request; return $this; } - + /** * Detach request from queue. * @@ -102,7 +103,7 @@ public function detach(Request $request) unset($this->queue[$request->getUID()]); return $this; } - + /** * Processes handles which are ready and removes them from pool. * @@ -115,11 +116,11 @@ protected function read() $n++; $request = $this->queue[(int)$info['handle']]; $result = $info['result']; - + curl_multi_remove_handle($this->mh, $request->getHandle()); unset($this->running[$request->getUID()]); $this->detach($request); - + $event = new Event(); $event->request = $request; $event->response = new Response($request, curl_multi_getcontent($request->getHandle())); @@ -130,20 +131,20 @@ protected function read() $this->dispatch('complete', $event); $request->dispatch('complete', $event); } - + return $n; } - + /** * Returns count of handles in queue - * + * * @return int Handles count */ public function count() { return count($this->queue); } - + /** * Executes requests in parallel * @@ -155,16 +156,16 @@ public function send() $this->socketSelect(); } } - + /** * Returns requests present in $queue but not in $running - * + * * @return Request[] Array of requests */ protected function getRequestsNotRunning() { $map = $this->queue; - foreach($this->running as $k => $v) unset($map[$k]); + foreach ($this->running as $k => $v) unset($map[$k]); return $map; } @@ -202,21 +203,21 @@ public function socketPerform() if ($runningHandles < count($this->running)) { $this->read(); } - + $notRunning = $this->getRequestsNotRunning(); } while (count($notRunning) > 0); // Why the loop? New requests might be added at runtime on 'complete' event. // So we need to attach them to curl_multi handle immediately. - + return $this->count() > 0; } - + /** * Waits until activity on socket * On success, returns TRUE. On failure, this function will * return FALSE on a select failure or timeout (from the underlying * select system call) - * + * * @param float|int $timeout Maximum time to wait * @throws Exception * @return bool diff --git a/src/RequestsQueueInterface.php b/src/RequestsQueueInterface.php index 8563541..127e8f9 100644 --- a/src/RequestsQueueInterface.php +++ b/src/RequestsQueueInterface.php @@ -1,13 +1,20 @@ ch = $request->getHandle(); - + if (is_string($content)) { $this->content = $content; } } - + /** * Get information regarding a current transfer * If opt is given, returns its value as a string @@ -35,20 +36,20 @@ public function getInfo($key = null) { return $key === null ? curl_getinfo($this->ch) : curl_getinfo($this->ch, $key); } - + /** * Returns content of request - * + * * @return string Content */ public function getContent() { return $this->content; } - + /** * Sets error instance - * + * * @param Error $error Error to set * @return void */ @@ -56,21 +57,21 @@ public function setError(Error $error) { $this->error = $error; } - + /** * Returns a error instance - * + * * @return Error|null */ public function getError() { return isset($this->error) ? $this->error : null; } - + /** - * Returns the error number for the last cURL operation. - * - * @return int Returns the error number or 0 (zero) if no error occurred. + * Returns the error number for the last cURL operation. + * + * @return int Returns the error number or 0 (zero) if no error occurred. */ public function hasError() { diff --git a/tests/ConstantsTableTest.php b/tests/ConstantsTableTest.php index d77fbf4..7d1ed9d 100644 --- a/tests/ConstantsTableTest.php +++ b/tests/ConstantsTableTest.php @@ -1,9 +1,10 @@ assertInstanceOf('cURL\Options', $opts); } - + public function testToArray() { $opts = new Options(); $array = $opts->toArray(); - + $this->assertInternalType('array', $array); $this->assertEmpty($array); } - + protected function assertsForSet(Options $opts) { $array = $opts->toArray(); $this->assertEquals(2, count($array)); - + $values = array( CURLOPT_TIMEOUT => 123, CURLOPT_USERAGENT => 'browser' ); - + foreach ($values as $key => $value) { $this->assertTrue($opts->has($key)); $this->assertEquals($value, $opts->get($key)); $this->assertEquals($value, $array[$key]); } - + $this->assertFalse($opts->has(CURLOPT_RETURNTRANSFER)); } - + public function testMissingOption() { $opts = new Options(); @@ -50,7 +51,7 @@ public function testMissingOption() } $this->assertInstanceOf('cURL\Exception', $e); } - + public function testSingleSet() { $opts = new Options(); @@ -58,7 +59,7 @@ public function testSingleSet() $opts->set(CURLOPT_USERAGENT, 'browser'); $this->assertsForSet($opts); } - + public function testArraySet() { $opts = new Options(); @@ -70,7 +71,7 @@ public function testArraySet() ); $this->assertsForSet($opts); } - + public function testIntelligentSet() { $opts = new Options(); @@ -90,23 +91,29 @@ public function testFluentSetters() { $opts = new Options(); $opts->setTimeout(123)->setUserAgent('browser'); + $this->assertEquals(123, $opts->get(CURLOPT_TIMEOUT)); + $this->assertEquals('browser', $opts->get(CURLOPT_USERAGENT)); + + $opts = new Options(); $opts->set(CURLOPT_TIMEOUT, 123)->set(CURLOPT_USERAGENT, 'browser'); + $this->assertEquals(123, $opts->get(CURLOPT_TIMEOUT)); + $this->assertEquals('browser', $opts->get(CURLOPT_USERAGENT)); } - + public function testRemove() { $opts = new Options(); $opts->set(CURLOPT_TIMEOUT, 123); $opts->set(CURLOPT_USERAGENT, 'browser'); - + $this->assertTrue($opts->has(CURLOPT_TIMEOUT)); $opts->remove(CURLOPT_TIMEOUT); $this->assertFalse($opts->has(CURLOPT_TIMEOUT)); - + $this->assertTrue($opts->has(CURLOPT_USERAGENT)); $opts->remove(CURLOPT_USERAGENT); $this->assertFalse($opts->has(CURLOPT_USERAGENT)); - + $this->assertEmpty($opts->toArray()); } } diff --git a/tests/RequestTest.php b/tests/RequestTest.php index 2e693e8..02769a4 100644 --- a/tests/RequestTest.php +++ b/tests/RequestTest.php @@ -1,4 +1,5 @@ getOptions(); $this->assertInstanceOf('cURL\Options', $opts); $this->assertEmpty($opts->toArray()); - + $opts = new cURL\Options(); $opts->set(CURLOPT_RETURNTRANSFER, true); $req->setOptions($opts); $this->assertEquals($opts, $req->getOptions()); - + } - + /** * Test synchronous request through send() */ @@ -36,7 +37,7 @@ public function testRequestSynchronous() ->set(CURLOPT_RETURNTRANSFER, true); $this->assertInternalType('resource', $req->getHandle()); $this->validateSuccesfulResponse($req->send()); - + /** * Timeouted request */ @@ -47,14 +48,14 @@ public function testRequestSynchronous() ->set(CURLOPT_RETURNTRANSFER, true); $this->validateTimeoutedResponse($req->send()); } - + /** * Test asynchronous request through socketPerform() and socketSelect() */ public function testRequestAsynchronous() { $test = $this; - + $req = new cURL\Request(); $req->getOptions() ->set(CURLOPT_URL, $this->createRequestUrl()) @@ -65,7 +66,7 @@ function ($event) use ($test) { $test->validateSuccesfulResponse($event->response); } ); - + $n = 0; while ($req->socketPerform()) { $n++; @@ -77,10 +78,10 @@ function ($event) use ($test) { $req->socketPerform(); } catch (cURL\Exception $e) { } - + $this->assertInstanceOf('cURL\Exception', $e); $this->assertGreaterThan(0, $n); - + $req = new cURL\Request(); $req->getOptions() ->set(CURLOPT_URL, $this->timeoutTestUrl) @@ -92,7 +93,7 @@ function ($event) use ($test) { $test->validateTimeoutedResponse($event->response); } ); - + while ($req->socketPerform()) { $req->socketSelect(); } diff --git a/tests/RequestsQueueTest.php b/tests/RequestsQueueTest.php index 82d9270..1545ecb 100644 --- a/tests/RequestsQueueTest.php +++ b/tests/RequestsQueueTest.php @@ -1,4 +1,5 @@ getDefaultOptions(); $this->assertInstanceOf('cURL\Options', $opts); $this->assertEmpty($opts->toArray()); - + $opts = new cURL\Options(); $opts->set(CURLOPT_URL, 'http://example-1/'); $opts->set(CURLOPT_USERAGENT, 'browser'); $q->setDefaultOptions($opts); $this->assertEquals($opts, $q->getDefaultOptions()); } - + /** * Returns RequestsQueue for tests - * + * * @return cURL\RequestsQueue Queue for tests */ protected function prepareTestQueue() @@ -55,20 +56,20 @@ function (cURL\Event $event) use ($test) { $test->validateSuccesfulResponse($event->response, $event->request->_param); } ); - + for ($i = 0; $i < 5; $i++) { $request = new cURL\Request(); $request->_param = $i; $request->getOptions()->set(CURLOPT_URL, $this->createRequestUrl($i)); $queue->attach($request); } - + $this->assertEquals(5, $queue->count()); $this->assertEquals(5, count($queue)); - + return $queue; } - + /** * Test request synchronous */ @@ -77,14 +78,14 @@ public function testQueueSynchronous() $queue = $this->prepareTestQueue(); $queue->send(); } - + /** * Test request asynchronous */ public function testQueueAsynchronous() { $queue = $this->prepareTestQueue(); - + while ($queue->socketPerform()) { $queue->socketSelect(); } @@ -94,10 +95,10 @@ public function testQueueAsynchronous() $queue->socketPerform(); } catch (cURL\Exception $e) { } - + $this->assertInstanceOf('cURL\Exception', $e); } - + /** * Test requests attaching on run time */ @@ -120,7 +121,7 @@ function (cURL\Event $event) use (&$n) { $queue->send(); $this->assertEquals(10, $n); } - + /** * Test requests attaching on run time */ @@ -132,8 +133,8 @@ public function testAttachNewOnRuntime() $queue->getDefaultOptions() ->set(CURLOPT_RETURNTRANSFER, true) ->set(CURLOPT_ENCODING, ''); - - + + $n = 0; $attachNew = function () use ($queue, &$n, $total) { if ($n < $total) { @@ -144,7 +145,7 @@ public function testAttachNewOnRuntime() $queue->attach($request); } }; - + $attachNew(); $queue->addListener( 'complete', diff --git a/tests/TestCase.php b/tests/TestCase.php index 94b868c..a77be95 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,16 +1,18 @@ okTestUrl.'?'.http_build_query(array('curl-easy' => $param)); + return $this->okTestUrl . '?' . http_build_query(array('curl-easy' => $param)); } public function validateSuccesfulResponse(Response $response, $param = 'ok') @@ -25,7 +27,7 @@ public function validateSuccesfulResponse(Response $response, $param = 'ok') $this->assertEquals(200, $response->getInfo(CURLINFO_HTTP_CODE)); $this->assertFalse($response->hasError()); } - + public function validateTimeoutedResponse(Response $response) { $this->assertEmpty($response->getContent());