Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions ext/spl/spl_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,15 +1341,6 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
}
break;
}
case DIT_AppendIterator:
if (zend_parse_parameters_none() == FAILURE) {
return NULL;
}
intern->dit_type = DIT_AppendIterator;
object_init_ex(&intern->u.append.zarrayit, spl_ce_ArrayIterator);
zend_call_method_with_0_params(Z_OBJ(intern->u.append.zarrayit), spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL);
intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 0);
return intern;
case DIT_RegexIterator:
case DIT_RecursiveRegexIterator: {
zend_string *regex;
Expand Down Expand Up @@ -2814,7 +2805,21 @@ static void spl_append_it_next(spl_dual_it_object *intern) /* {{{ */
/* {{{ Create an AppendIterator */
PHP_METHOD(AppendIterator, __construct)
{
spl_dual_it_construct(INTERNAL_FUNCTION_PARAM_PASSTHRU, spl_ce_AppendIterator, zend_ce_iterator, DIT_AppendIterator);
ZEND_PARSE_PARAMETERS_NONE();

spl_dual_it_object *intern = Z_SPLDUAL_IT_P(ZEND_THIS);

/* TODO: This should be converted to a normal Error as this is triggered when calling the constructor twice */
if (intern->dit_type != DIT_Unknown) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "%s::getIterator() must be called exactly once per instance", ZSTR_VAL(spl_ce_AppendIterator->name));
RETURN_THROWS();
}

intern->dit_type = DIT_AppendIterator;
object_init_ex(&intern->u.append.zarrayit, spl_ce_ArrayIterator);
zend_call_method_with_0_params(Z_OBJ(intern->u.append.zarrayit), spl_ce_ArrayIterator, &spl_ce_ArrayIterator->constructor, "__construct", NULL);
intern->u.append.iterator = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, &intern->u.append.zarrayit, 0);

} /* }}} */

/* {{{ Append an iterator */
Expand Down
31 changes: 15 additions & 16 deletions ext/spl/tests/iterator_031.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ SPL: AppendIterator::append() rewinds when necessary
--FILE--
<?php

$ap = new AppendIterator();
try {
$ap->__construct();
} catch (\Throwable $e) {
echo $e::class, ': ', $e->getMessage(), "\n";
}

class MyArrayIterator extends ArrayIterator
{
function rewind(): void
Expand All @@ -14,8 +21,7 @@ class MyArrayIterator extends ArrayIterator

$it = new MyArrayIterator(array(1,2));

foreach($it as $k=>$v)
{
foreach($it as $k=>$v) {
echo "$k=>$v\n";
}

Expand Down Expand Up @@ -44,45 +50,38 @@ class MyAppendIterator extends AppendIterator
parent::append($what);
}

function parent__construct()
{
function parent__construct() {
parent::__construct();
}
}

$ap = new MyAppendIterator;

try
{
try {
$ap->append($it);
}
catch(\Error $e)
{
} catch(\Error $e) {
echo $e->getMessage() . "\n";
}

$ap->parent__construct();

try
{
try {
$ap->parent__construct($it);
}
catch(BadMethodCallException $e)
{
} catch(BadMethodCallException $e) {
echo $e->getMessage() . "\n";
}

$ap->append($it);
$ap->append($it);
$ap->append($it);

foreach($ap as $k=>$v)
{
foreach($ap as $k=>$v) {
echo "$k=>$v\n";
}

?>
--EXPECT--
BadMethodCallException: AppendIterator::getIterator() must be called exactly once per instance
MyArrayIterator::rewind
0=>1
1=>2
Expand Down
Loading