From 96b3d50c2eaaaf0e303b7d93bef612adead884e2 Mon Sep 17 00:00:00 2001 From: Zach Borboa Date: Sat, 24 Dec 2016 12:16:10 -0800 Subject: [PATCH 1/5] Simplify setCookie tests --- tests/PHPCurlClass/PHPCurlClassTest.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/PHPCurlClass/PHPCurlClassTest.php b/tests/PHPCurlClass/PHPCurlClassTest.php index b9f3987..50fcb0b 100644 --- a/tests/PHPCurlClass/PHPCurlClassTest.php +++ b/tests/PHPCurlClass/PHPCurlClassTest.php @@ -957,9 +957,8 @@ class CurlTest extends PHPUnit_Framework_TestCase { $test = new Test(); $test->curl->setCookie('mycookie', 'yum'); - $this->assertEquals('yum', $test->server('cookie', 'GET', array( - 'key' => 'mycookie', - ))); + $test->server('setcookie', 'GET'); + $this->assertEquals('yum', $test->curl->responseCookies['mycookie']); } public function testSetCookies() @@ -971,9 +970,11 @@ class CurlTest extends PHPUnit_Framework_TestCase ); $test = new Test(); $test->curl->setCookies($cookies); - $test->server('cookie', 'GET'); + $test->server('setcookie', 'GET'); - $this->assertEquals(http_build_query($cookies, '', '&'), $test->curl->response); + $this->assertEquals('yum', $test->curl->responseCookies['mycookie']); + $this->assertEquals('apple', $test->curl->responseCookies['fruit']); + $this->assertEquals('red', $test->curl->responseCookies['color']); } public function testSetCookieEncodingSpace() From abc7dc2f53dbcb8e15579cdf637d0a9fc4e844e1 Mon Sep 17 00:00:00 2001 From: Zach Borboa Date: Sat, 24 Dec 2016 12:47:58 -0800 Subject: [PATCH 2/5] Use Curl::getOpt() instead of reflection --- tests/PHPCurlClass/PHPCurlClassTest.php | 61 ++++--------------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/tests/PHPCurlClass/PHPCurlClassTest.php b/tests/PHPCurlClass/PHPCurlClassTest.php index 50fcb0b..77221ae 100644 --- a/tests/PHPCurlClass/PHPCurlClassTest.php +++ b/tests/PHPCurlClass/PHPCurlClassTest.php @@ -981,12 +981,7 @@ class CurlTest extends PHPUnit_Framework_TestCase { $curl = new Curl(); $curl->setCookie('cookie', 'Om nom nom nom'); - - $reflectionClass = new ReflectionClass('\Curl\Curl'); - $reflectionProperty = $reflectionClass->getProperty('options'); - $reflectionProperty->setAccessible(true); - $options = $reflectionProperty->getValue($curl); - $this->assertEquals('cookie=Om%20nom%20nom%20nom', $options[CURLOPT_COOKIE]); + $this->assertEquals('cookie=Om%20nom%20nom%20nom', $curl->getOpt(CURLOPT_COOKIE)); } public function testSetMultipleCookies() @@ -994,24 +989,14 @@ class CurlTest extends PHPUnit_Framework_TestCase $curl = new Curl(); $curl->setCookie('cookie', 'Om nom nom nom'); $curl->setCookie('foo', 'bar'); - - $reflectionClass = new ReflectionClass('\Curl\Curl'); - $reflectionProperty = $reflectionClass->getProperty('options'); - $reflectionProperty->setAccessible(true); - $options = $reflectionProperty->getValue($curl); - $this->assertEquals('cookie=Om%20nom%20nom%20nom; foo=bar', $options[CURLOPT_COOKIE]); + $this->assertEquals('cookie=Om%20nom%20nom%20nom; foo=bar', $curl->getOpt(CURLOPT_COOKIE)); } public function testSetCookieEncodingColon() { $curl = new Curl(); $curl->setCookie('JSESSIONID', '0000wd-PcsB3bZ-KzYGAqm_rKlm:17925chrl'); - - $reflectionClass = new ReflectionClass('\Curl\Curl'); - $reflectionProperty = $reflectionClass->getProperty('options'); - $reflectionProperty->setAccessible(true); - $options = $reflectionProperty->getValue($curl); - $this->assertEquals('JSESSIONID=0000wd-PcsB3bZ-KzYGAqm_rKlm:17925chrl', $options[CURLOPT_COOKIE]); + $this->assertEquals('JSESSIONID=0000wd-PcsB3bZ-KzYGAqm_rKlm:17925chrl', $curl->getOpt(CURLOPT_COOKIE)); } public function testSetCookieString() @@ -1020,12 +1005,7 @@ class CurlTest extends PHPUnit_Framework_TestCase $test = new Test(); $test->curl->setCookieString($cookie_string); - - $reflectionClass = new ReflectionClass('\Curl\Curl'); - $reflectionProperty = $reflectionClass->getProperty('options'); - $reflectionProperty->setAccessible(true); - $options = $reflectionProperty->getValue($test->curl); - $this->assertEquals($cookie_string, $options[CURLOPT_COOKIE]); + $this->assertEquals($cookie_string, $test->curl->getOpt(CURLOPT_COOKIE)); $this->assertEquals('fruit=apple&color=red', $test->server('cookie', 'GET')); } @@ -3005,27 +2985,16 @@ class CurlTest extends PHPUnit_Framework_TestCase $curl = new Curl(); $success = $curl->setOpt($option, $value); - $reflector = new ReflectionObject($curl); - $property = $reflector->getProperty('options'); - $property->setAccessible(true); - $options = $property->getValue($curl); - $this->assertTrue($success); - $this->assertTrue(isset($options[$option])); - $this->assertEquals($value, $options[$option]); + $this->assertEquals($value, $curl->getOpt($option)); // Ensure the option is not stored when curl_setopt() fails. Make curl_setopt() return false and suppress // errors. Triggers warning: "curl_setopt(): Curl option contains invalid characters (\0)". $curl = new Curl(); $success = @$curl->setOpt($option, $null); - $reflector = new ReflectionObject($curl); - $property = $reflector->getProperty('options'); - $property->setAccessible(true); - $options = $property->getValue($curl); - $this->assertFalse($success); - $this->assertFalse(isset($options[$option])); + $this->assertNull($curl->getOpt($option)); // Ensure options following a Curl::setOpt() failure are not set when using Curl::setOpts(). $options = array( @@ -3035,13 +3004,8 @@ class CurlTest extends PHPUnit_Framework_TestCase $curl = new Curl(); $success = @$curl->setOpts($options); - $reflector = new ReflectionObject($curl); - $property = $reflector->getProperty('options'); - $property->setAccessible(true); - $options = $property->getValue($curl); - $this->assertFalse($success); - $this->assertFalse(isset($options[CURLOPT_COOKIE])); + $this->assertNull($curl->getOpt(CURLOPT_COOKIE)); // Ensure Curl::setOpts() returns true when all options are successfully set. $options = array( @@ -3052,15 +3016,10 @@ class CurlTest extends PHPUnit_Framework_TestCase $curl = new Curl(); $success = $curl->setOpts($options); - $reflector = new ReflectionObject($curl); - $property = $reflector->getProperty('options'); - $property->setAccessible(true); - $options = $property->getValue($curl); - $this->assertTrue($success); - $this->assertEquals('a=b', $options[CURLOPT_COOKIE]); - $this->assertTrue($options[CURLOPT_FOLLOWLOCATION]); - $this->assertTrue($options[CURLOPT_VERBOSE]); + $this->assertEquals('a=b', $curl->getOpt(CURLOPT_COOKIE)); + $this->assertTrue($curl->getOpt(CURLOPT_FOLLOWLOCATION)); + $this->assertTrue($curl->getOpt(CURLOPT_VERBOSE)); } public function testBuildUrlArgSeparator() From bf701e7f3f9c590ee25947cdd46a1ecbcc9ac937 Mon Sep 17 00:00:00 2001 From: Zach Borboa Date: Sat, 24 Dec 2016 12:52:17 -0800 Subject: [PATCH 3/5] Move large rfc variables down --- src/Curl/Curl.php | 66 +++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index 3e63340..dc769eb 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -7,39 +7,6 @@ class Curl const VERSION = '7.1.0'; const DEFAULT_TIMEOUT = 30; - public static $RFC2616 = array( - // RFC2616: "any CHAR except CTLs or separators". - // CHAR = - // CTL = - // separators = "(" | ")" | "<" | ">" | "@" - // | "," | ";" | ":" | "\" | <"> - // | "/" | "[" | "]" | "?" | "=" - // | "{" | "}" | SP | HT - // SP = - // HT = - // <"> = - '!', '#', '$', '%', '&', "'", '*', '+', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', - 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', - 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~', - ); - public static $RFC6265 = array( - // RFC6265: "US-ASCII characters excluding CTLs, whitespace DQUOTE, comma, semicolon, and backslash". - // %x21 - '!', - // %x23-2B - '#', '$', '%', '&', "'", '(', ')', '*', '+', - // %x2D-3A - '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', - // %x3C-5B - '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', - 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', - // %x5D-7E - ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', - 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', - ); - public $curl; public $id = null; @@ -81,6 +48,39 @@ class Curl private $xmlPattern = '~^(?:text/|application/(?:atom\+|rss\+)?)xml~i'; private $defaultDecoder = null; + public static $RFC2616 = array( + // RFC2616: "any CHAR except CTLs or separators". + // CHAR = + // CTL = + // separators = "(" | ")" | "<" | ">" | "@" + // | "," | ";" | ":" | "\" | <"> + // | "/" | "[" | "]" | "?" | "=" + // | "{" | "}" | SP | HT + // SP = + // HT = + // <"> = + '!', '#', '$', '%', '&', "'", '*', '+', '-', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '|', '~', + ); + public static $RFC6265 = array( + // RFC6265: "US-ASCII characters excluding CTLs, whitespace DQUOTE, comma, semicolon, and backslash". + // %x21 + '!', + // %x23-2B + '#', '$', '%', '&', "'", '(', ')', '*', '+', + // %x2D-3A + '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', + // %x3C-5B + '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', + // %x5D-7E + ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', + ); + private static $deferredProperties = array( 'effectiveUrl', 'rfc2616', From b6e6524d29b88e8a0a611e9a7a93f311d4608b24 Mon Sep 17 00:00:00 2001 From: Zach Borboa Date: Sat, 24 Dec 2016 13:04:12 -0800 Subject: [PATCH 4/5] Move array methods to separate file --- README.md | 3 - src/Curl/ArrayUtil.php | 80 +++++++++++++++++++++++++ src/Curl/Curl.php | 78 +----------------------- tests/PHPCurlClass/PHPCurlClassTest.php | 4 +- 4 files changed, 84 insertions(+), 81 deletions(-) create mode 100644 src/Curl/ArrayUtil.php diff --git a/README.md b/README.md index be11422..d3e0cbb 100644 --- a/README.md +++ b/README.md @@ -242,9 +242,6 @@ Curl::setXmlDecoder($function) Curl::success($callback) Curl::unsetHeader($key) Curl::verbose($on = true, $output = STDERR) -Curl::array_flatten_multidim($array, $prefix = false) -Curl::is_array_assoc($array) -Curl::is_array_multidim($array) MultiCurl::__construct($base_url = null) MultiCurl::__destruct() MultiCurl::addCurl(Curl $curl) diff --git a/src/Curl/ArrayUtil.php b/src/Curl/ArrayUtil.php new file mode 100644 index 0000000..0cd5088 --- /dev/null +++ b/src/Curl/ArrayUtil.php @@ -0,0 +1,80 @@ + $value) { + if (is_scalar($value)) { + if ($prefix) { + $return[$prefix . '[' . $key . ']'] = $value; + } else { + $return[$key] = $value; + } + } else { + if ($value instanceof \CURLFile) { + $return[$key] = $value; + } else { + $return = array_merge( + $return, + self::array_flatten_multidim( + $value, + $prefix ? $prefix . '[' . $key . ']' : $key + ) + ); + } + } + } + } + } elseif ($array === null) { + $return[$prefix] = $array; + } + return $return; + } +} diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index dc769eb..b3d424f 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -148,8 +148,8 @@ class Curl // Manually build a single-dimensional array from a multi-dimensional array as using curl_setopt($ch, // CURLOPT_POSTFIELDS, $data) doesn't correctly handle multi-dimensional arrays when files are // referenced. - if (self::is_array_multidim($data)) { - $data = self::array_flatten_multidim($data); + if (\Curl\ArrayUtil::is_array_multidim($data)) { + $data = \Curl\ArrayUtil::array_flatten_multidim($data); } // Modify array values to ensure any referenced files are properly handled depending on the support of @@ -1379,78 +1379,4 @@ class Curl } return $response_headers; } - - /** - * Is Array Assoc - * - * @access public - * @param $array - * - * @return boolean - */ - public static function is_array_assoc($array) - { - return (bool)count(array_filter(array_keys($array), 'is_string')); - } - - /** - * Is Array Multidim - * - * @access public - * @param $array - * - * @return boolean - */ - public static function is_array_multidim($array) - { - if (!is_array($array)) { - return false; - } - - return (bool)count(array_filter($array, 'is_array')); - } - - /** - * Array Flatten Multidim - * - * @access public - * @param $array - * @param $prefix - * - * @return array - */ - public static function array_flatten_multidim($array, $prefix = false) - { - $return = array(); - if (is_array($array) || is_object($array)) { - if (empty($array)) { - $return[$prefix] = ''; - } else { - foreach ($array as $key => $value) { - if (is_scalar($value)) { - if ($prefix) { - $return[$prefix . '[' . $key . ']'] = $value; - } else { - $return[$key] = $value; - } - } else { - if ($value instanceof \CURLFile) { - $return[$key] = $value; - } else { - $return = array_merge( - $return, - self::array_flatten_multidim( - $value, - $prefix ? $prefix . '[' . $key . ']' : $key - ) - ); - } - } - } - } - } elseif ($array === null) { - $return[$prefix] = $array; - } - return $return; - } } diff --git a/tests/PHPCurlClass/PHPCurlClassTest.php b/tests/PHPCurlClass/PHPCurlClassTest.php index 77221ae..3553cb3 100644 --- a/tests/PHPCurlClass/PHPCurlClassTest.php +++ b/tests/PHPCurlClass/PHPCurlClassTest.php @@ -14,7 +14,7 @@ class CurlTest extends PHPUnit_Framework_TestCase public function testArrayAssociative() { - $this->assertTrue(Curl::is_array_assoc(array( + $this->assertTrue(\Curl\ArrayUtil::is_array_assoc(array( 'foo' => 'wibble', 'bar' => 'wubble', 'baz' => 'wobble', @@ -23,7 +23,7 @@ class CurlTest extends PHPUnit_Framework_TestCase public function testArrayIndexed() { - $this->assertFalse(Curl::is_array_assoc(array( + $this->assertFalse(\Curl\ArrayUtil::is_array_assoc(array( 'wibble', 'wubble', 'wobble', From 7dc6eba0af3f86379f59a6c35c7e4f68e34038a9 Mon Sep 17 00:00:00 2001 From: Zach Borboa Date: Sun, 25 Dec 2016 01:45:16 -0500 Subject: [PATCH 5/5] Process multicurl requests in ascending numerical order. Previously, multicurl requests were added to the end and removed from the end. Requests are now added to the end and removed from the beginning. Using array_shift() will be slower than array_pop(). Before using "array_push()" + array_pop(): 1 1 2 1 2 3 1 2 3 4 1 2 3 1 2 1 After using "array_push()" + array_shift(): 1 1 2 1 2 3 1 2 3 4 2 3 4 3 4 4 --- src/Curl/MultiCurl.php | 4 ++-- tests/PHPCurlClass/PHPMultiCurlClassTest.php | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Curl/MultiCurl.php b/src/Curl/MultiCurl.php index de13050..c79b81c 100644 --- a/src/Curl/MultiCurl.php +++ b/src/Curl/MultiCurl.php @@ -641,7 +641,7 @@ class MultiCurl } for ($i = 0; $i < $concurrency; $i++) { - $this->initHandle(array_pop($this->curls)); + $this->initHandle(array_shift($this->curls)); } do { @@ -662,7 +662,7 @@ class MultiCurl // Start a new request before removing the handle of the completed one. if (count($this->curls) >= 1) { - $this->initHandle(array_pop($this->curls)); + $this->initHandle(array_shift($this->curls)); } curl_multi_remove_handle($this->multiCurl, $ch->curl); diff --git a/tests/PHPCurlClass/PHPMultiCurlClassTest.php b/tests/PHPCurlClass/PHPMultiCurlClassTest.php index 7f26464..8417f51 100644 --- a/tests/PHPCurlClass/PHPMultiCurlClassTest.php +++ b/tests/PHPCurlClass/PHPMultiCurlClassTest.php @@ -2486,4 +2486,22 @@ class MultiCurlTest extends PHPUnit_Framework_TestCase $this->assertEquals($sequential_id, $instance->id); } } + + public function testAscendingNumericalOrder() + { + $counter = 0; + $multi_curl = new MultiCurl(); + $multi_curl->setConcurrency(1); + $multi_curl->complete(function ($instance) use (&$counter) { + $sequential_id = $instance->getOpt(CURLOPT_POSTFIELDS); + PHPUnit_Framework_Assert::assertEquals($counter, $sequential_id); + $counter++; + }); + + for ($i = 0; $i < 100; $i++) { + $multi_curl->addPost(Test::TEST_URL, $i); + } + + $multi_curl->start(); + } }