Skip to content

Commit 9d43a42

Browse files
Add new flag ARRAY_FILTER_PACK_RESULT
1 parent 533162d commit 9d43a42

7 files changed

Lines changed: 144 additions & 8 deletions

File tree

ext/standard/array.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6511,13 +6511,19 @@ PHP_FUNCTION(array_filter)
65116511
Z_PARAM_LONG(use_type)
65126512
ZEND_PARSE_PARAMETERS_END();
65136513

6514+
bool pack_result = use_type & ARRAY_FILTER_PACK_RESULT;
6515+
use_type &= ~ARRAY_FILTER_PACK_RESULT;
6516+
65146517
switch (use_type) {
65156518
case ARRAY_FILTER_USE_VALUE:
65166519
case ARRAY_FILTER_USE_BOTH:
65176520
case ARRAY_FILTER_USE_KEY:
65186521
break;
65196522
default:
6520-
zend_argument_value_error(3, "must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH");
6523+
zend_argument_value_error(
6524+
3,
6525+
"must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH (optionally combined with ARRAY_FILTER_PACK_RESULT)"
6526+
);
65216527
RETURN_THROWS();
65226528
}
65236529

@@ -6567,7 +6573,9 @@ PHP_FUNCTION(array_filter)
65676573
continue;
65686574
}
65696575

6570-
if (string_key) {
6576+
if (pack_result) {
6577+
operand = zend_hash_next_index_insert(Z_ARRVAL_P(return_value), operand);
6578+
} else if (string_key) {
65716579
operand = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, operand);
65726580
} else {
65736581
operand = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, operand);

ext/standard/basic_functions.stub.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ enum SortDirection {
132132
* @cvalue ARRAY_FILTER_USE_KEY
133133
*/
134134
const ARRAY_FILTER_USE_KEY = UNKNOWN;
135+
/**
136+
* @var int
137+
* @cvalue ARRAY_FILTER_PACK_RESULT
138+
*/
139+
const ARRAY_FILTER_PACK_RESULT = UNKNOWN;
135140

136141
/* assert.c */
137142

ext/standard/basic_functions_arginfo.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/basic_functions_decl.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/standard/php_array.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ PHPAPI bool php_array_pick_keys(php_random_algo_with_state engine, zval *input,
6060
#define ARRAY_FILTER_USE_VALUE 0
6161
#define ARRAY_FILTER_USE_BOTH 1
6262
#define ARRAY_FILTER_USE_KEY 2
63+
#define ARRAY_FILTER_PACK_RESULT 4
6364

6465
extern PHPAPI zend_class_entry *sort_direction_ce;
6566

ext/standard/tests/array/array_filter_invalid_mode.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ try {
1212
echo "Done"
1313
?>
1414
--EXPECT--
15-
ValueError: array_filter(): Argument #3 ($mode) must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH
15+
ValueError: array_filter(): Argument #3 ($mode) must be one of ARRAY_FILTER_USE_VALUE, ARRAY_FILTER_USE_KEY, or ARRAY_FILTER_USE_BOTH (optionally combined with ARRAY_FILTER_PACK_RESULT)
1616
Done
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
--TEST--
2+
array_filter() tests with ARRAY_FILTER_PACK_RESULT
3+
--FILE--
4+
<?php
5+
6+
$array1 = [false, null, true, '', 'foo', 0, 123];
7+
var_dump( array_filter( $array1 ) );
8+
var_dump( array_filter( $array1, null, ARRAY_FILTER_PACK_RESULT ) );
9+
10+
$array2 = [
11+
'index 0 means false key',
12+
'' => 'false key empty string',
13+
false,
14+
];
15+
// to filter based on a truthy key requires an explicit callback
16+
var_dump( array_filter( $array2, fn ($v) => $v, ARRAY_FILTER_USE_KEY ) );
17+
var_dump( array_filter( $array2, fn ($v) => $v, ARRAY_FILTER_USE_KEY | ARRAY_FILTER_PACK_RESULT ) );
18+
19+
$array3 = [
20+
'key1' => true,
21+
'key2' => false,
22+
'key3' => 123,
23+
];
24+
function filter( $value, $key ) {
25+
$value = var_export( $value, true );
26+
echo 'Filter: $key => $value\n';
27+
return true;
28+
}
29+
var_dump( array_filter( $array3, filter(...), ARRAY_FILTER_USE_BOTH ) );
30+
var_dump( array_filter( $array3, filter(...), ARRAY_FILTER_USE_BOTH | ARRAY_FILTER_PACK_RESULT ) );
31+
32+
$array4 = [
33+
123,
34+
true,
35+
false,
36+
(object)[],
37+
[],
38+
456,
39+
'123',
40+
];
41+
var_dump( array_filter( $array4, is_int(...) ) );
42+
var_dump( array_filter( $array4, is_int(...), ARRAY_FILTER_PACK_RESULT ) );
43+
44+
$array4 = [
45+
'first int' => 123,
46+
'true' => true,
47+
'false' => false,
48+
'object' => (object)[],
49+
'array' => [],
50+
'second int' => 456,
51+
'int-looking string' => '123',
52+
];
53+
var_dump( array_filter( $array4, is_int(...) ) );
54+
var_dump( array_filter( $array4, is_int(...), ARRAY_FILTER_PACK_RESULT ) );
55+
56+
?>
57+
--EXPECT--
58+
array(3) {
59+
[2]=>
60+
bool(true)
61+
[4]=>
62+
string(3) "foo"
63+
[6]=>
64+
int(123)
65+
}
66+
array(3) {
67+
[0]=>
68+
bool(true)
69+
[1]=>
70+
string(3) "foo"
71+
[2]=>
72+
int(123)
73+
}
74+
array(1) {
75+
[1]=>
76+
bool(false)
77+
}
78+
array(1) {
79+
[0]=>
80+
bool(false)
81+
}
82+
Filter: $key => $value\nFilter: $key => $value\nFilter: $key => $value\narray(3) {
83+
["key1"]=>
84+
bool(true)
85+
["key2"]=>
86+
bool(false)
87+
["key3"]=>
88+
int(123)
89+
}
90+
Filter: $key => $value\nFilter: $key => $value\nFilter: $key => $value\narray(3) {
91+
[0]=>
92+
bool(true)
93+
[1]=>
94+
bool(false)
95+
[2]=>
96+
int(123)
97+
}
98+
array(2) {
99+
[0]=>
100+
int(123)
101+
[5]=>
102+
int(456)
103+
}
104+
array(2) {
105+
[0]=>
106+
int(123)
107+
[1]=>
108+
int(456)
109+
}
110+
array(2) {
111+
["first int"]=>
112+
int(123)
113+
["second int"]=>
114+
int(456)
115+
}
116+
array(2) {
117+
[0]=>
118+
int(123)
119+
[1]=>
120+
int(456)
121+
}

0 commit comments

Comments
 (0)