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 3e63340..b3d424f 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', @@ -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/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/PHPCurlClassTest.php b/tests/PHPCurlClass/PHPCurlClassTest.php index b9f3987..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', @@ -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,21 +970,18 @@ 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() { $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() @@ -993,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() @@ -1019,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')); } @@ -3004,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( @@ -3034,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( @@ -3051,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() 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(); + } }