mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
- Allow to hook into RecursiveIteratorIterator's child handling
- Better=faster function caching for RecursiveIteratorIterator - Check for exceptions and fix check for illegal return values - Add UnexpectedValueException - Add docu
This commit is contained in:
parent
6dc04d98f2
commit
f9de3fd02b
6 changed files with 473 additions and 13 deletions
|
@ -252,6 +252,8 @@ class BadMethodCallException extends BadFunctionCallException
|
|||
*
|
||||
* This kind of exception should be used to inform about domain erors in
|
||||
* mathematical sense.
|
||||
*
|
||||
* @see RangeException
|
||||
*/
|
||||
class DomainException extends LogicException
|
||||
{
|
||||
|
@ -260,6 +262,8 @@ class DomainException extends LogicException
|
|||
/** @ingroup SPL
|
||||
* @brief Exception that denotes invalid arguments were passed.
|
||||
* @since PHP 5.1
|
||||
*
|
||||
* @see UnexpectedValueException
|
||||
*/
|
||||
class InvalidArgumentException extends LogicException
|
||||
{
|
||||
|
@ -321,19 +325,36 @@ class OverflowException extends RuntimeException
|
|||
* @since PHP 5.1
|
||||
*
|
||||
* Normally this means there was an arithmetic error other than under/overflow.
|
||||
* This is the runtime version of DomainException.
|
||||
*
|
||||
* @see DomainException
|
||||
*/
|
||||
class RangeException extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
||||
/** @ingroup SPL
|
||||
* @brief Exception Exception thrown to indicate arithmetic/buffer underflow.
|
||||
* @brief Exception thrown to indicate arithmetic/buffer underflow.
|
||||
* @since PHP 5.1
|
||||
*/
|
||||
class UnderflowException extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
||||
/** @ingroup SPL
|
||||
* @brief Exception thrown to indicate an unexpected value.
|
||||
* @since PHP 5.1
|
||||
*
|
||||
* Typically this happens when a function calls another function and espects
|
||||
* the return value to be of a certain type or value not including arithmetic
|
||||
* or buffer related errors.
|
||||
*
|
||||
* @see InvalidArgumentException
|
||||
*/
|
||||
class UnexpectedValueException extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
||||
/** @ingroup ZendEngine
|
||||
* @brief Interface to override array access of objects.
|
||||
* @since PHP 5.0
|
||||
|
|
|
@ -45,6 +45,7 @@ PHPAPI zend_class_entry *spl_ce_OutOfBoundsException;
|
|||
PHPAPI zend_class_entry *spl_ce_OverflowException;
|
||||
PHPAPI zend_class_entry *spl_ce_RangeException;
|
||||
PHPAPI zend_class_entry *spl_ce_UnderflowException;
|
||||
PHPAPI zend_class_entry *spl_ce_UnexpectedValueException;
|
||||
|
||||
#define spl_ce_Exception zend_exception_get_default()
|
||||
|
||||
|
@ -64,6 +65,7 @@ PHP_MINIT_FUNCTION(spl_exceptions)
|
|||
REGISTER_SPL_SUB_CLASS_EX(OverflowException, RuntimeException, NULL, NULL);
|
||||
REGISTER_SPL_SUB_CLASS_EX(RangeException, RuntimeException, NULL, NULL);
|
||||
REGISTER_SPL_SUB_CLASS_EX(UnderflowException, RuntimeException, NULL, NULL);
|
||||
REGISTER_SPL_SUB_CLASS_EX(UnexpectedValueException, RuntimeException, NULL, NULL);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ extern PHPAPI zend_class_entry *spl_ce_OutOfBoundsException;
|
|||
extern PHPAPI zend_class_entry *spl_ce_OverflowException;
|
||||
extern PHPAPI zend_class_entry *spl_ce_RangeException;
|
||||
extern PHPAPI zend_class_entry *spl_ce_UnderflowException;
|
||||
extern PHPAPI zend_class_entry *spl_ce_UnexpectedValueException;
|
||||
|
||||
PHP_MINIT_FUNCTION(spl_exceptions);
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ typedef struct _spl_recursive_it_object {
|
|||
spl_sub_iterator *iterators;
|
||||
int level;
|
||||
RecursiveIteratorMode mode;
|
||||
zend_function *callHasChildren;
|
||||
zend_function *callGetChildren;
|
||||
zend_function *beginChildren;
|
||||
zend_function *endChildren;
|
||||
zend_class_entry *ce;
|
||||
|
@ -183,7 +185,11 @@ next_step:
|
|||
case RS_TEST:
|
||||
ce = object->iterators[object->level].ce;
|
||||
zobject = object->iterators[object->level].zobject;
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
|
||||
if (object->callHasChildren) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->callHasChildren, "callHasChildren", &retval);
|
||||
} else {
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
|
||||
}
|
||||
if (retval) {
|
||||
has_children = zend_is_true(retval);
|
||||
zval_ptr_dtor(&retval);
|
||||
|
@ -211,13 +217,17 @@ next_step:
|
|||
case RS_CHILD:
|
||||
ce = object->iterators[object->level].ce;
|
||||
zobject = object->iterators[object->level].zobject;
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child);
|
||||
ce = child ? Z_OBJCE_P(child) : NULL;
|
||||
if (object->callGetChildren) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->callGetChildren, "callGetChildren", &child);
|
||||
} else {
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &child);
|
||||
}
|
||||
ce = child && Z_TYPE_P(child) == IS_OBJECT ? Z_OBJCE_P(child) : NULL;
|
||||
if (!ce || !instanceof_function(ce, spl_ce_RecursiveIterator TSRMLS_CC)) {
|
||||
if (child) {
|
||||
zval_ptr_dtor(&child);
|
||||
}
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0 TSRMLS_CC);
|
||||
zend_throw_exception(spl_ce_UnexpectedValueException, "Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
if (object->mode == RIT_CHILD_FIRST) {
|
||||
|
@ -234,7 +244,7 @@ next_step:
|
|||
if (sub_iter->funcs->rewind) {
|
||||
sub_iter->funcs->rewind(sub_iter TSRMLS_CC);
|
||||
}
|
||||
if (!object->beginChildren || object->beginChildren->common.scope != spl_ce_RecursiveIteratorIterator) {
|
||||
if (object->beginChildren) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->beginChildren, "beginchildren", NULL);
|
||||
}
|
||||
goto next_step;
|
||||
|
@ -244,7 +254,7 @@ next_step:
|
|||
iterator->funcs->dtor(iterator TSRMLS_CC);
|
||||
zval_ptr_dtor(&object->iterators[object->level].zobject);
|
||||
object->level--;
|
||||
if (!object->endChildren || object->endChildren->common.scope != spl_ce_RecursiveIteratorIterator) {
|
||||
if (object->endChildren) {
|
||||
zend_call_method_with_0_params(&zthis, object->ce, &object->endChildren, "endchildren", NULL);
|
||||
}
|
||||
} else {
|
||||
|
@ -335,9 +345,23 @@ SPL_METHOD(RecursiveIteratorIterator, __construct)
|
|||
intern->iterators = emalloc(sizeof(spl_sub_iterator));
|
||||
intern->level = 0;
|
||||
intern->mode = mode;
|
||||
intern->beginChildren = NULL;
|
||||
intern->endChildren = NULL;
|
||||
intern->ce = Z_OBJCE_P(object);
|
||||
zend_hash_find(&intern->ce->function_table, "callhaschildren", sizeof("callHasChildren"), (void **) &intern->callHasChildren);
|
||||
if (intern->callHasChildren->common.scope == spl_ce_RecursiveIteratorIterator) {
|
||||
intern->callHasChildren = NULL;
|
||||
}
|
||||
zend_hash_find(&intern->ce->function_table, "callgetchildren", sizeof("callGetChildren"), (void **) &intern->callGetChildren);
|
||||
if (intern->callGetChildren->common.scope == spl_ce_RecursiveIteratorIterator) {
|
||||
intern->callGetChildren = NULL;
|
||||
}
|
||||
zend_hash_find(&intern->ce->function_table, "beginchildren", sizeof("beginchildren"), (void **) &intern->beginChildren);
|
||||
if (intern->beginChildren->common.scope == spl_ce_RecursiveIteratorIterator) {
|
||||
intern->beginChildren = NULL;
|
||||
}
|
||||
zend_hash_find(&intern->ce->function_table, "endchildren", sizeof("endchildren"), (void **) &intern->endChildren);
|
||||
if (intern->endChildren->common.scope == spl_ce_RecursiveIteratorIterator) {
|
||||
intern->endChildren = NULL;
|
||||
}
|
||||
ce_iterator = Z_OBJCE_P(iterator); /* respect inheritance, don't use spl_ce_RecursiveIterator */
|
||||
intern->iterators[0].iterator = ce_iterator->get_iterator(ce_iterator, iterator TSRMLS_CC);
|
||||
iterator->refcount++;
|
||||
|
@ -443,6 +467,40 @@ SPL_METHOD(RecursiveIteratorIterator, getInnerIterator)
|
|||
RETURN_ZVAL(object->iterators[level].zobject, 1, 0);
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto bool RecursiveIteratorIterator::callHasChildren()
|
||||
Called for each element to test whether it has children */
|
||||
SPL_METHOD(RecursiveIteratorIterator, callHasChildren)
|
||||
{
|
||||
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
zend_class_entry *ce = object->iterators[object->level].ce;
|
||||
zval *retval, *zobject;
|
||||
|
||||
zobject = object->iterators[object->level].zobject;
|
||||
if (!zobject) {
|
||||
RETURN_FALSE;
|
||||
} else {
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "haschildren", &retval);
|
||||
RETURN_ZVAL(retval, 0, 1);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::callGetChildren()
|
||||
Return children of current element */
|
||||
SPL_METHOD(RecursiveIteratorIterator, callGetChildren)
|
||||
{
|
||||
spl_recursive_it_object *object = (spl_recursive_it_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
zend_class_entry *ce = object->iterators[object->level].ce;
|
||||
zval *retval, *zobject;
|
||||
|
||||
zobject = object->iterators[object->level].zobject;
|
||||
if (!zobject) {
|
||||
return;
|
||||
} else {
|
||||
zend_call_method_with_0_params(&zobject, ce, NULL, "getchildren", &retval);
|
||||
RETURN_ZVAL(retval, 0, 1);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ proto RecursiveIterator RecursiveIteratorIterator::beginChildren()
|
||||
Called when recursing one level down */
|
||||
SPL_METHOD(RecursiveIteratorIterator, beginChildren)
|
||||
|
@ -538,10 +596,12 @@ static zend_function_entry spl_funcs_RecursiveIteratorIterator[] = {
|
|||
SPL_ME(RecursiveIteratorIterator, current, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, next, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getDepth, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getSubIterator,arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getInnerIterator,NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, beginChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, endChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getSubIterator, arginfo_recursive_it_getSubIterator, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, getInnerIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, callHasChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, callGetChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, beginChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(RecursiveIteratorIterator, endChildren, NULL, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
185
ext/spl/tests/iterator_021.phpt
Executable file
185
ext/spl/tests/iterator_021.phpt
Executable file
|
@ -0,0 +1,185 @@
|
|||
--TEST--
|
||||
SPL: RecursiveIteratorIterator and hasChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
if (!parent::valid())
|
||||
{
|
||||
echo __METHOD__ . " = false\n";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
{
|
||||
private $max_depth;
|
||||
private $over = 0;
|
||||
private $skip = false;
|
||||
|
||||
function __construct($it, $max_depth)
|
||||
{
|
||||
$this->max_depth = $max_depth;
|
||||
parent::__construct($it);
|
||||
}
|
||||
|
||||
function rewind()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
$this->skip = false;
|
||||
parent::rewind();
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
if ($this->skip)
|
||||
{
|
||||
$this->skip = false;
|
||||
$this->next();
|
||||
}
|
||||
return parent::valid();
|
||||
}
|
||||
|
||||
function current()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::current();
|
||||
}
|
||||
|
||||
function key()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::key();
|
||||
}
|
||||
|
||||
function next()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
parent::next();
|
||||
}
|
||||
|
||||
function callHasChildren()
|
||||
{
|
||||
$this->skip = false;
|
||||
$has = parent::callHasChildren();
|
||||
$res = $this->getDepth() < $this->max_depth && $has;
|
||||
echo __METHOD__ . "(".$this->getDepth().") = ".($res?"yes":"no")."/".($has?"yes":"no")."\n";
|
||||
if ($has && !$res)
|
||||
{
|
||||
$this->over++;
|
||||
if ($this->over == 2) {
|
||||
$this->skip = true;
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function beginChildren()
|
||||
{
|
||||
echo __METHOD__ . "(".$this->getDepth().")\n";
|
||||
}
|
||||
|
||||
function endChildren()
|
||||
{
|
||||
echo __METHOD__ . "(".$this->getDepth().")\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
{
|
||||
if (is_array($v)) $v = join('',$v);
|
||||
echo "$k=>$v\n";
|
||||
}
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECTF--
|
||||
RecursiveArrayIteratorIterator::rewind
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>a
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>bba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>bcaa
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(0)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIterator::getChildren
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ca
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(0)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
3=>d
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIterator::valid = false
|
||||
===DONE===
|
191
ext/spl/tests/iterator_022.phpt
Executable file
191
ext/spl/tests/iterator_022.phpt
Executable file
|
@ -0,0 +1,191 @@
|
|||
--TEST--
|
||||
SPL: RecursiveIteratorIterator and callHasChildren/callGetChildren
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator
|
||||
{
|
||||
function hasChildren()
|
||||
{
|
||||
return is_array($this->current());
|
||||
}
|
||||
|
||||
function getChildren()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
if (!parent::valid())
|
||||
{
|
||||
echo __METHOD__ . " = false\n";
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RecursiveArrayIteratorIterator extends RecursiveIteratorIterator
|
||||
{
|
||||
private $max_depth;
|
||||
private $over = 0;
|
||||
private $skip = false;
|
||||
|
||||
function __construct($it, $max_depth)
|
||||
{
|
||||
$this->max_depth = $max_depth;
|
||||
parent::__construct($it);
|
||||
}
|
||||
|
||||
function rewind()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
$this->skip = false;
|
||||
parent::rewind();
|
||||
}
|
||||
|
||||
function valid()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
if ($this->skip)
|
||||
{
|
||||
$this->skip = false;
|
||||
$this->next();
|
||||
}
|
||||
return parent::valid();
|
||||
}
|
||||
|
||||
function current()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::current();
|
||||
}
|
||||
|
||||
function key()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
return parent::key();
|
||||
}
|
||||
|
||||
function next()
|
||||
{
|
||||
echo __METHOD__ . "\n";
|
||||
parent::next();
|
||||
}
|
||||
|
||||
function callHasChildren()
|
||||
{
|
||||
$this->skip = false;
|
||||
$has = parent::callHasChildren();
|
||||
$res = $this->getDepth() < $this->max_depth && $has;
|
||||
echo __METHOD__ . "(".$this->getDepth().") = ".($res?"yes":"no")."/".($has?"yes":"no")."\n";
|
||||
if ($has && !$res)
|
||||
{
|
||||
$this->over++;
|
||||
if ($this->over == 2) {
|
||||
$this->skip = true;
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
function callGetChildren()
|
||||
{
|
||||
if ($this->over == 2)
|
||||
{
|
||||
echo __METHOD__ . "(skip)\n";
|
||||
return NULL;
|
||||
}
|
||||
echo __METHOD__ . "(ok:{$this->over})\n";
|
||||
return new RecursiveArrayIterator($this->current());
|
||||
}
|
||||
|
||||
function beginChildren()
|
||||
{
|
||||
echo __METHOD__ . "(".$this->getDepth().")\n";
|
||||
}
|
||||
|
||||
function endChildren()
|
||||
{
|
||||
echo __METHOD__ . "(".$this->getDepth().")\n";
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach(new RecursiveArrayIteratorIterator(new RecursiveArrayIterator(array("a", array("ba", array("bba", "bbb"), array(array("bcaa"), array("bcba"))), array("ca"), "d")), 2) as $k=>$v)
|
||||
{
|
||||
if (is_array($v)) $v = join('',$v);
|
||||
echo "$k=>$v\n";
|
||||
}
|
||||
}
|
||||
catch(UnexpectedValueException $e)
|
||||
{
|
||||
echo $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
<?php exit(0); ?>
|
||||
--EXPECTF--
|
||||
RecursiveArrayIteratorIterator::rewind
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>a
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(ok:0)
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::beginChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>ba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(ok:0)
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>bba
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/no
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
1=>bbb
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(1) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(ok:0)
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::beginChildren(2)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::current
|
||||
RecursiveArrayIteratorIterator::key
|
||||
0=>bcaa
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIteratorIterator::callHasChildren(2) = no/yes
|
||||
RecursiveArrayIteratorIterator::valid
|
||||
RecursiveArrayIteratorIterator::next
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(1)
|
||||
RecursiveArrayIterator::valid = false
|
||||
RecursiveArrayIteratorIterator::endChildren(0)
|
||||
RecursiveArrayIteratorIterator::callHasChildren(0) = yes/yes
|
||||
RecursiveArrayIteratorIterator::callGetChildren(skip)
|
||||
Objects returned by RecursiveIterator::getChildren() must implement RecursiveIterator
|
||||
===DONE===
|
Loading…
Add table
Add a link
Reference in a new issue