mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Added CallbackFilterIterator and RecursiveCallbackFilterIterator classes
[DOC] This is a concrete FilterIterator which takes a callback as constructor parameter, and uses this callback for filtering. This allows to use FilterIterator without extending it. CallbackFilterIterator Example: $it = new ArrayIterator(range(1,100)); $it = new CallbackFilterIterator($it, function($value) { return $value % 2; }); foreach($it as $value) // ... RecursiveCallbackFilterIterator Example: $it = new RecursiveDirectoryIterator("/"); $it = new RecursiveCallbackFilterIterator($it, function($file, $k, $it) { return $it->hasChildren() || $file->getSize() > 1024; }); foreach(new RecursiveIteratorIterator($it) as $file) // ... The callback takes the current value, the current key and the inner iterator as parameters.
This commit is contained in:
parent
2191af9546
commit
b83e243c23
6 changed files with 494 additions and 0 deletions
1
NEWS
1
NEWS
|
@ -197,6 +197,7 @@ PHP NEWS
|
|||
. Added RegexIterator::getRegex() method. (Joshua Thijssen)
|
||||
. Added SplObjectStorage::getHash() hook. (Etienne)
|
||||
. Added SplFileInfo::getExtension(). FR #48767. (Peter Cowburn)
|
||||
. Added CallbackFilterIterator and RecursiveCallbackFilterIterator (Arnaud)
|
||||
|
||||
- Improved ZLIB extension:
|
||||
. Re-implemented non-file related functionality. (Mike)
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_FilterIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_CallbackFilterIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_RecursiveCallbackFilterIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_ParentIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_SeekableIterator;
|
||||
PHPAPI zend_class_entry *spl_ce_LimitIterator;
|
||||
|
@ -1499,6 +1501,23 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
case DIT_CallbackFilterIterator:
|
||||
case DIT_RecursiveCallbackFilterIterator: {
|
||||
_spl_cbfilter_it_intern *cfi = emalloc(sizeof(*cfi));
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Of", &zobject, ce_inner, &cfi->fci, &cfi->fcc) == FAILURE) {
|
||||
zend_restore_error_handling(&error_handling TSRMLS_CC);
|
||||
efree(cfi);
|
||||
return NULL;
|
||||
}
|
||||
if (cfi->fci.function_name) {
|
||||
Z_ADDREF_P(cfi->fci.function_name);
|
||||
}
|
||||
if (cfi->fci.object_ptr) {
|
||||
Z_ADDREF_P(cfi->fci.object_ptr);
|
||||
}
|
||||
intern->u.cbfilter = cfi;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobject, ce_inner) == FAILURE) {
|
||||
zend_restore_error_handling(&error_handling TSRMLS_CC);
|
||||
|
@ -1527,6 +1546,13 @@ SPL_METHOD(FilterIterator, __construct)
|
|||
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_FilterIterator, zend_ce_iterator, DIT_FilterIterator);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto void CallbackFilterIterator::__construct(Iterator it, callback)
|
||||
Create an Iterator from another iterator */
|
||||
SPL_METHOD(CallbackFilterIterator, __construct)
|
||||
{
|
||||
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_CallbackFilterIterator, zend_ce_iterator, DIT_CallbackFilterIterator);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto Iterator FilterIterator::getInnerIterator()
|
||||
proto Iterator CachingIterator::getInnerIterator()
|
||||
proto Iterator LimitIterator::getInnerIterator()
|
||||
|
@ -1800,6 +1826,14 @@ SPL_METHOD(FilterIterator, next)
|
|||
spl_filter_it_next(getThis(), intern TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto void RecursiveCallbackFilterIterator::__construct(RecursiveIterator it, callback)
|
||||
Create a RecursiveCallbackFilterIterator from a RecursiveIterator */
|
||||
SPL_METHOD(RecursiveCallbackFilterIterator, __construct)
|
||||
{
|
||||
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RecursiveCallbackFilterIterator, spl_ce_RecursiveIterator, DIT_RecursiveCallbackFilterIterator);
|
||||
} /* }}} */
|
||||
|
||||
|
||||
/* {{{ proto void RecursiveFilterIterator::__construct(RecursiveIterator it)
|
||||
Create a RecursiveFilterIterator from a RecursiveIterator */
|
||||
SPL_METHOD(RecursiveFilterIterator, __construct)
|
||||
|
@ -1850,6 +1884,27 @@ SPL_METHOD(RecursiveFilterIterator, getChildren)
|
|||
}
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto RecursiveCallbackFilterIterator RecursiveCallbackFilterIterator::getChildren()
|
||||
Return the inner iterator's children contained in a RecursiveCallbackFilterIterator */
|
||||
SPL_METHOD(RecursiveCallbackFilterIterator, getChildren)
|
||||
{
|
||||
spl_dual_it_object *intern;
|
||||
zval *retval;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
|
||||
zend_call_method_with_0_params(&intern->inner.zobject, intern->inner.ce, NULL, "getchildren", &retval);
|
||||
if (!EG(exception) && retval) {
|
||||
spl_instantiate_arg_ex2(Z_OBJCE_P(getThis()), &return_value, 0, retval, intern->u.cbfilter->fci.function_name TSRMLS_CC);
|
||||
}
|
||||
if (retval) {
|
||||
zval_ptr_dtor(&retval);
|
||||
}
|
||||
} /* }}} */
|
||||
/* {{{ proto void ParentIterator::__construct(RecursiveIterator it)
|
||||
Create a ParentIterator from a RecursiveIterator */
|
||||
SPL_METHOD(ParentIterator, __construct)
|
||||
|
@ -1865,6 +1920,53 @@ SPL_METHOD(RegexIterator, __construct)
|
|||
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_RegexIterator, zend_ce_iterator, DIT_RegexIterator);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto bool CallbackFilterIterator::accept()
|
||||
Calls the callback with the current value, the current key and the inner iterator as arguments */
|
||||
SPL_METHOD(CallbackFilterIterator, accept)
|
||||
{
|
||||
spl_dual_it_object *intern = (spl_dual_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
zend_fcall_info *fci = &intern->u.cbfilter->fci;
|
||||
zend_fcall_info_cache *fcc = &intern->u.cbfilter->fcc;
|
||||
zval **params[3];
|
||||
zval zkey;
|
||||
zval *zkey_p = &zkey;
|
||||
zval *result;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (intern->current.data == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
INIT_PZVAL(&zkey);
|
||||
if (intern->current.key_type == HASH_KEY_IS_LONG) {
|
||||
ZVAL_LONG(&zkey, intern->current.int_key);
|
||||
} else {
|
||||
ZVAL_STRINGL(&zkey, intern->current.str_key, intern->current.str_key_len-1, 0);
|
||||
}
|
||||
|
||||
params[0] = &intern->current.data;
|
||||
params[1] = &zkey_p;
|
||||
params[2] = &intern->inner.zobject;
|
||||
|
||||
fci->retval_ptr_ptr = &result;
|
||||
fci->param_count = 3;
|
||||
fci->params = params;
|
||||
fci->no_separation = 0;
|
||||
|
||||
if (zend_call_function(fci, fcc TSRMLS_CC) != SUCCESS || !result) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (EG(exception)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_ZVAL(result, 1, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool RegexIterator::accept()
|
||||
Match (string)current() against regular expression */
|
||||
SPL_METHOD(RegexIterator, accept)
|
||||
|
@ -2154,6 +2256,18 @@ static void spl_dual_it_free_storage(void *_object TSRMLS_DC)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (object->dit_type == DIT_CallbackFilterIterator || object->dit_type == DIT_RecursiveCallbackFilterIterator) {
|
||||
if (object->u.cbfilter) {
|
||||
if (object->u.cbfilter->fci.function_name) {
|
||||
zval_ptr_dtor(&object->u.cbfilter->fci.function_name);
|
||||
}
|
||||
if (object->u.cbfilter->fci.object_ptr) {
|
||||
zval_ptr_dtor(&object->u.cbfilter->fci.object_ptr);
|
||||
}
|
||||
efree(object->u.cbfilter);
|
||||
}
|
||||
}
|
||||
|
||||
zend_object_std_dtor(&object->std TSRMLS_CC);
|
||||
|
||||
efree(object);
|
||||
|
@ -2195,6 +2309,29 @@ static const zend_function_entry spl_funcs_FilterIterator[] = {
|
|||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_callback_filter_it___construct, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
|
||||
ZEND_ARG_INFO(0, callback)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static const zend_function_entry spl_funcs_CallbackFilterIterator[] = {
|
||||
SPL_ME(CallbackFilterIterator, __construct, arginfo_callback_filter_it___construct, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(CallbackFilterIterator, accept, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_recursive_callback_filter_it___construct, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
|
||||
ZEND_ARG_INFO(0, callback)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static const zend_function_entry spl_funcs_RecursiveCallbackFilterIterator[] = {
|
||||
SPL_ME(RecursiveCallbackFilterIterator, __construct, arginfo_recursive_callback_filter_it___construct, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveFilterIterator, hasChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveCallbackFilterIterator, getChildren, arginfo_recursive_it_void, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_parent_it___construct, 0)
|
||||
ZEND_ARG_OBJ_INFO(0, iterator, RecursiveIterator, 0)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
@ -3535,6 +3672,12 @@ PHP_MINIT_FUNCTION(spl_iterators)
|
|||
REGISTER_SPL_SUB_CLASS_EX(RecursiveFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_RecursiveFilterIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(RecursiveFilterIterator, RecursiveIterator);
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(CallbackFilterIterator, FilterIterator, spl_dual_it_new, spl_funcs_CallbackFilterIterator);
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(RecursiveCallbackFilterIterator, CallbackFilterIterator, spl_dual_it_new, spl_funcs_RecursiveCallbackFilterIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(RecursiveCallbackFilterIterator, RecursiveIterator);
|
||||
|
||||
|
||||
REGISTER_SPL_SUB_CLASS_EX(ParentIterator, RecursiveFilterIterator, spl_dual_it_new, spl_funcs_ParentIterator);
|
||||
|
||||
REGISTER_SPL_INTERFACE(Countable);
|
||||
|
|
|
@ -75,6 +75,8 @@ typedef enum {
|
|||
DIT_RegexIterator,
|
||||
DIT_RecursiveRegexIterator,
|
||||
#endif
|
||||
DIT_CallbackFilterIterator,
|
||||
DIT_RecursiveCallbackFilterIterator,
|
||||
DIT_Unknown = ~0
|
||||
} dual_it_type;
|
||||
|
||||
|
@ -114,6 +116,11 @@ typedef enum {
|
|||
REGIT_MODE_MAX
|
||||
} regex_mode;
|
||||
|
||||
typedef struct _spl_cbfilter_it_intern {
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fcc;
|
||||
} _spl_cbfilter_it_intern;
|
||||
|
||||
typedef struct _spl_dual_it_object {
|
||||
zend_object std;
|
||||
struct {
|
||||
|
@ -157,6 +164,7 @@ typedef struct _spl_dual_it_object {
|
|||
uint regex_len;
|
||||
} regex;
|
||||
#endif
|
||||
_spl_cbfilter_it_intern *cbfilter;
|
||||
} u;
|
||||
} spl_dual_it_object;
|
||||
|
||||
|
|
71
ext/spl/tests/CallbackFilterIteratorTest-002.phpt
Normal file
71
ext/spl/tests/CallbackFilterIteratorTest-002.phpt
Normal file
|
@ -0,0 +1,71 @@
|
|||
--TEST--
|
||||
CallbackFilterIterator 002
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
set_error_handler(function($errno, $errstr){
|
||||
echo $errstr . "\n";
|
||||
return true;
|
||||
});
|
||||
|
||||
try {
|
||||
new CallbackFilterIterator();
|
||||
} catch(InvalidArgumentException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
new CallbackFilterIterator(null);
|
||||
} catch(InvalidArgumentException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
new CallbackFilterIterator(new ArrayIterator(array()), null);
|
||||
} catch(InvalidArgumentException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
new CallbackFilterIterator(new ArrayIterator(array()), array());
|
||||
} catch(InvalidArgumentException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
$it = new CallbackFilterIterator(new ArrayIterator(array(1)), function() {
|
||||
throw new Exception("some message");
|
||||
});
|
||||
try {
|
||||
foreach($it as $e);
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
class Test extends CallbackFilterIterator {
|
||||
function __construct(){}
|
||||
}
|
||||
class Test2 extends RecursiveCallbackFilterIterator {
|
||||
function __construct(){}
|
||||
}
|
||||
|
||||
try {
|
||||
new Test;
|
||||
} catch(LogicException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
new Test2;
|
||||
} catch(LogicException $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
--EXPECT--
|
||||
CallbackFilterIterator::__construct() expects exactly 2 parameters, 0 given
|
||||
Argument 1 passed to CallbackFilterIterator::__construct() must implement interface Iterator, null given
|
||||
CallbackFilterIterator::__construct() expects exactly 2 parameters, 1 given
|
||||
CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, no array or string given
|
||||
CallbackFilterIterator::__construct() expects parameter 2 to be a valid callback, array must have exactly two members
|
||||
some message
|
||||
In the constructor of Test, parent::__construct() must be called and its exceptions cannot be cleared
|
||||
In the constructor of Test2, parent::__construct() must be called and its exceptions cannot be cleared
|
133
ext/spl/tests/CallbackFilterIteratorTest.phpt
Normal file
133
ext/spl/tests/CallbackFilterIteratorTest.phpt
Normal file
|
@ -0,0 +1,133 @@
|
|||
--TEST--
|
||||
CallbackFilterIterator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function test($value, $key, $inner) {
|
||||
return test($value, $key, $inner);
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
static function test($value, $key, $inner) {
|
||||
return test($value, $key, $inner);
|
||||
}
|
||||
}
|
||||
|
||||
function test($value, $key, $inner) {
|
||||
printf("%s / %s / %d / %d\n"
|
||||
, $value
|
||||
, $key
|
||||
, $value == $inner->current()
|
||||
, $key == $inner->key()
|
||||
);
|
||||
return $value === 1 || $value === 4;
|
||||
}
|
||||
|
||||
$tests = array(
|
||||
'instance method' => function() { return array(new A, 'test'); },
|
||||
'static method' => function() { return array('B', 'test'); },
|
||||
'static method (2)' => function() { return 'B::test'; },
|
||||
'function' => function() { return 'test'; },
|
||||
'anonymous function' => function() { return function($value, $key, $inner) { return test($value, $key, $inner); }; },
|
||||
);
|
||||
|
||||
foreach($tests as $name => $test) {
|
||||
|
||||
$callback = $test();
|
||||
$it = new ArrayIterator(range(1, 5));
|
||||
$it = new CallbackFilterIterator($it, $callback);
|
||||
|
||||
echo " = $name =\n";
|
||||
|
||||
foreach($it as $value) {
|
||||
echo "=> $value\n";
|
||||
}
|
||||
|
||||
// same test, with no reference to callback
|
||||
|
||||
$it = new ArrayIterator(range(1, 5));
|
||||
$it = new CallbackFilterIterator($it, $test());
|
||||
unset($callback);
|
||||
|
||||
foreach($it as $value) {
|
||||
echo "=> $value\n";
|
||||
}
|
||||
}
|
||||
--EXPECT--
|
||||
= instance method =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
= static method =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
= static method (2) =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
= function =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
= anonymous function =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 1 / 1 / 1
|
||||
3 / 2 / 1 / 1
|
||||
4 / 3 / 1 / 1
|
||||
=> 4
|
||||
5 / 4 / 1 / 1
|
138
ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt
Normal file
138
ext/spl/tests/RecursiveCallbackFilterIteratorTest.phpt
Normal file
|
@ -0,0 +1,138 @@
|
|||
--TEST--
|
||||
RecursiveCallbackFilterIterator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
function test($value, $key, $inner) {
|
||||
return test($value, $key, $inner);
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
static function test($value, $key, $inner) {
|
||||
return test($value, $key, $inner);
|
||||
}
|
||||
}
|
||||
|
||||
function test($value, $key, $inner) {
|
||||
if ($inner->hasChildren()) {
|
||||
return true;
|
||||
}
|
||||
printf("%s / %s / %d / %d\n"
|
||||
, print_r($value, true)
|
||||
, $key
|
||||
, $value == $inner->current()
|
||||
, $key == $inner->key()
|
||||
);
|
||||
return $value === 1 || $value === 4;
|
||||
}
|
||||
|
||||
$tests = array(
|
||||
'instance method' => function() { return array(new A, 'test'); },
|
||||
'static method' => function() { return array('B', 'test'); },
|
||||
'static method (2)' => function() { return 'B::test'; },
|
||||
'function' => function() { return 'test'; },
|
||||
'anonymous function' => function() { return function($value, $key, $inner) { return test($value, $key, $inner); }; },
|
||||
);
|
||||
|
||||
foreach($tests as $name => $test) {
|
||||
|
||||
$callback = $test();
|
||||
$it = new RecursiveArrayIterator(array(1, array(2, 3), array(4, 5)));
|
||||
$it = new RecursiveCallbackFilterIterator($it, $callback);
|
||||
$it = new RecursiveIteratorIterator($it);
|
||||
|
||||
echo " = $name =\n";
|
||||
|
||||
foreach($it as $value) {
|
||||
echo "=> $value\n";
|
||||
}
|
||||
|
||||
// same test, with no reference to callback
|
||||
|
||||
$it = new RecursiveArrayIterator(array(1, array(2, 3), array(4, 5)));
|
||||
$it = new RecursiveCallbackFilterIterator($it, $test());
|
||||
$it = new RecursiveIteratorIterator($it);
|
||||
unset($callback);
|
||||
|
||||
foreach($it as $value) {
|
||||
echo "=> $value\n";
|
||||
}
|
||||
}
|
||||
--EXPECT--
|
||||
= instance method =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
= static method =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
= static method (2) =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
= function =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
= anonymous function =
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
||||
1 / 0 / 1 / 1
|
||||
=> 1
|
||||
2 / 0 / 1 / 1
|
||||
3 / 1 / 1 / 1
|
||||
4 / 0 / 1 / 1
|
||||
=> 4
|
||||
5 / 1 / 1 / 1
|
Loading…
Add table
Add a link
Reference in a new issue