mirror of
https://github.com/php-curl-class/php-curl-class.git
synced 2026-08-30 04:01:47 +00:00
Merge pull request #419 from zachborboa/master
Process multicurl requests in ascending numerical order
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Curl;
|
||||
|
||||
class ArrayUtil
|
||||
{
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
+35
-109
@@ -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 = <any US-ASCII character (octets 0 - 127)>
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
// separators = "(" | ")" | "<" | ">" | "@"
|
||||
// | "," | ";" | ":" | "\" | <">
|
||||
// | "/" | "[" | "]" | "?" | "="
|
||||
// | "{" | "}" | SP | HT
|
||||
// SP = <US-ASCII SP, space (32)>
|
||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
// <"> = <US-ASCII double-quote mark (34)>
|
||||
'!', '#', '$', '%', '&', "'", '*', '+', '-', '.', '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 = <any US-ASCII character (octets 0 - 127)>
|
||||
// CTL = <any US-ASCII control character
|
||||
// (octets 0 - 31) and DEL (127)>
|
||||
// separators = "(" | ")" | "<" | ">" | "@"
|
||||
// | "," | ";" | ":" | "\" | <">
|
||||
// | "/" | "[" | "]" | "?" | "="
|
||||
// | "{" | "}" | SP | HT
|
||||
// SP = <US-ASCII SP, space (32)>
|
||||
// HT = <US-ASCII HT, horizontal-tab (9)>
|
||||
// <"> = <US-ASCII double-quote mark (34)>
|
||||
'!', '#', '$', '%', '&', "'", '*', '+', '-', '.', '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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user