Skip to content

Commit 7ae7df5

Browse files
authored
1 parent 37cf7f6 commit 7ae7df5

10 files changed

+113
-14
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ PHP NEWS
4848
- Random:
4949
. Added new random extension. (Go Kudo)
5050

51+
- SPL:
52+
. Widen iterator_to_array() and iterator_count()'s $iterator parameter to
53+
iterable. (timwolla)
54+
5155
- Standard:
5256
. Fixed empty array returned by str_split on empty input. (Michael Vorisek)
5357
. Added ini_parse_quantity function to convert ini quantities shorthand

UPGRADING

+5
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ PHP 8.2 UPGRADE NOTES
189189
dba_fetch(string|array $key, $skip, $dba): string|false
190190
is still accepted, but it is recommended to use the new standard variant.
191191

192+
- SPL
193+
. The $iterator parameter of iterator_to_array() and iterator_count() is
194+
widened to iterable from Iterator, allowing arrays to be passed.
195+
RFC: https://wiki.php.net/rfc/iterator_xyz_accept_array
196+
192197
========================================
193198
6. New Functions
194199
========================================

ext/spl/php_spl.stub.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function spl_object_id(object $object): int {}
4848

4949
function iterator_apply(Traversable $iterator, callable $callback, ?array $args = null): int {}
5050

51-
function iterator_count(Traversable $iterator): int {}
51+
function iterator_count(iterable $iterator): int {}
5252

5353
/** @refcount 1 */
54-
function iterator_to_array(Traversable $iterator, bool $preserve_keys = true): array {}
54+
function iterator_to_array(iterable $iterator, bool $preserve_keys = true): array {}

ext/spl/php_spl_arginfo.h

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/spl/spl_iterators.c

+21-7
Original file line numberDiff line numberDiff line change
@@ -3171,8 +3171,18 @@ PHP_FUNCTION(iterator_to_array)
31713171
zval *obj;
31723172
bool use_keys = 1;
31733173

3174-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &obj, zend_ce_traversable, &use_keys) == FAILURE) {
3175-
RETURN_THROWS();
3174+
ZEND_PARSE_PARAMETERS_START(1, 2)
3175+
Z_PARAM_ITERABLE(obj)
3176+
Z_PARAM_OPTIONAL
3177+
Z_PARAM_BOOL(use_keys)
3178+
ZEND_PARSE_PARAMETERS_END();
3179+
3180+
if (Z_TYPE_P(obj) == IS_ARRAY) {
3181+
if (use_keys) {
3182+
RETURN_COPY(obj);
3183+
} else {
3184+
RETURN_ARR(zend_array_to_list(Z_ARRVAL_P(obj)));
3185+
}
31763186
}
31773187

31783188
array_init(return_value);
@@ -3195,12 +3205,16 @@ PHP_FUNCTION(iterator_count)
31953205
zval *obj;
31963206
zend_long count = 0;
31973207

3198-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &obj, zend_ce_traversable) == FAILURE) {
3199-
RETURN_THROWS();
3200-
}
3208+
ZEND_PARSE_PARAMETERS_START(1, 1)
3209+
Z_PARAM_ITERABLE(obj)
3210+
ZEND_PARSE_PARAMETERS_END();
32013211

3202-
if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count) == FAILURE) {
3203-
return;
3212+
if (Z_TYPE_P(obj) == IS_ARRAY) {
3213+
count = zend_hash_num_elements(Z_ARRVAL_P(obj));
3214+
} else {
3215+
if (spl_iterator_apply(obj, spl_iterator_count_apply, (void*)&count) == FAILURE) {
3216+
RETURN_THROWS();
3217+
}
32043218
}
32053219

32063220
RETURN_LONG(count);

ext/spl/tests/iterator_count.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ iterator_count('1');
1313

1414
?>
1515
--EXPECTF--
16-
Fatal error: Uncaught TypeError: iterator_count(): Argument #1 ($iterator) must be of type Traversable, string given in %s:%d
16+
Fatal error: Uncaught TypeError: iterator_count(): Argument #1 ($iterator) must be of type Traversable|array, string given in %s:%d
1717
Stack trace:
1818
#0 %s(%d): iterator_count('1')
1919
#1 {main}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
SPL: iterator_count() supports arrays.
3+
--FILE--
4+
<?php
5+
6+
var_dump(iterator_count([]));
7+
var_dump(iterator_count([1]));
8+
var_dump(iterator_count(['a' => 1, 'b' => 2, 5 => 3]));
9+
10+
?>
11+
--EXPECT--
12+
int(0)
13+
int(1)
14+
int(3)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
SPL: iterator_count() throws if the Iterator throws
3+
--FILE--
4+
<?php
5+
6+
function generator() {
7+
yield 1;
8+
throw new Exception('Iterator failed');
9+
}
10+
11+
var_dump(iterator_count(generator()));
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught Exception: Iterator failed in %siterator_count_exception.php:5
16+
Stack trace:
17+
#0 [internal function]: generator()
18+
#1 %siterator_count_exception.php(8): iterator_count(Object(Generator))
19+
#2 {main}
20+
thrown in %siterator_count_exception.php on line 5

ext/spl/tests/iterator_to_array.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ iterator_to_array('test','test');
1313

1414
?>
1515
--EXPECTF--
16-
Fatal error: Uncaught TypeError: iterator_to_array(): Argument #1 ($iterator) must be of type Traversable, string given in %s:%d
16+
Fatal error: Uncaught TypeError: iterator_to_array(): Argument #1 ($iterator) must be of type Traversable|array, string given in %s:%d
1717
Stack trace:
1818
#0 %s(%d): iterator_to_array('test', 'test')
1919
#1 {main}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
SPL: iterator_to_array() supports arrays.
3+
--FILE--
4+
<?php
5+
6+
var_dump(iterator_to_array([]));
7+
var_dump(iterator_to_array([1]));
8+
var_dump(iterator_to_array(['a' => 1, 'b' => 2, 5 => 3]));
9+
var_dump(iterator_to_array([], false));
10+
var_dump(iterator_to_array([1], false));
11+
var_dump(iterator_to_array(['a' => 1, 'b' => 2, 5 => 3], false));
12+
13+
?>
14+
--EXPECT--
15+
array(0) {
16+
}
17+
array(1) {
18+
[0]=>
19+
int(1)
20+
}
21+
array(3) {
22+
["a"]=>
23+
int(1)
24+
["b"]=>
25+
int(2)
26+
[5]=>
27+
int(3)
28+
}
29+
array(0) {
30+
}
31+
array(1) {
32+
[0]=>
33+
int(1)
34+
}
35+
array(3) {
36+
[0]=>
37+
int(1)
38+
[1]=>
39+
int(2)
40+
[2]=>
41+
int(3)
42+
}

0 commit comments

Comments
 (0)