Skip to content

Commit 1ca1985

Browse files
committed
Align array_flip() function to official PHP
1 parent f1a5c7e commit 1ca1985

16 files changed

+200
-133
lines changed

src/ph7/hashmap.c

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5004,16 +5004,24 @@ static int ph7_hashmap_flip(ph7_context *pCtx,int nArg,ph7_value **apArg)
50045004
ph7_value *pKey;
50055005
ph7_value sVal;
50065006
sxu32 n;
5007-
if( nArg < 1 ){
5008-
/* Missing arguments,return NULL */
5009-
ph7_result_null(pCtx);
5010-
return PH7_OK;
5007+
5008+
/* PHP requires exactly one argument */
5009+
if( nArg != 1 ){
5010+
/* Use ArgumentCountError like other array helpers */
5011+
return PH7_VmThrowException(pCtx,
5012+
"ArgumentCountError",
5013+
"array_flip() expects exactly 1 argument, %d given",
5014+
nArg
5015+
);
50115016
}
50125017
/* Make sure we are dealing with a valid hashmap */
50135018
if( !ph7_value_is_array(apArg[0]) ){
5014-
/* Invalid argument,return NULL */
5015-
ph7_result_null(pCtx);
5016-
return PH7_OK;
5019+
/* Type mismatch -> TypeError */
5020+
return PH7_VmThrowException(pCtx,
5021+
"TypeError",
5022+
"array_flip(): Argument #1 ($array) must be of type array, %s given",
5023+
ph7_type_name(apArg[0])
5024+
);
50175025
}
50185026
/* Point to the internal representation of the input hashmap */
50195027
pSrc = (ph7_hashmap *)apArg[0]->x.pOther;
@@ -5026,23 +5034,35 @@ static int ph7_hashmap_flip(ph7_context *pCtx,int nArg,ph7_value **apArg)
50265034
/* Start processing */
50275035
pEntry = pSrc->pFirst;
50285036
for( n = 0 ; n < pSrc->nEntry ; n++ ){
5029-
/* Extract the node value */
5037+
/* Extract the node value (will become a key in the result) */
50305038
pKey = HashmapExtractNodeValue(pEntry);
5031-
if( pKey && (pKey->iFlags & MEMOBJ_NULL) == 0){
5032-
/* Prepare the value for insertion */
5033-
if( pEntry->iType == HASHMAP_INT_NODE ){
5034-
PH7_MemObjInitFromInt(pSrc->pVm,&sVal,pEntry->xKey.iKey);
5039+
if( pKey ){
5040+
/* NULL values are not valid keys either, PHP emits a warning */
5041+
if( pKey->iFlags & MEMOBJ_NULL ){
5042+
PH7_VmThrowError(pCtx->pVm,0,PH7_CTX_WARNING,
5043+
"array_flip(): Can only flip string and integer values, entry skipped"
5044+
);
5045+
}else if( (pKey->iFlags & MEMOBJ_INT) || (pKey->iFlags & MEMOBJ_STRING) ){
5046+
/* Prepare the value for insertion (original key) */
5047+
if( pEntry->iType == HASHMAP_INT_NODE ){
5048+
PH7_MemObjInitFromInt(pSrc->pVm,&sVal,pEntry->xKey.iKey);
5049+
}else{
5050+
SyString sStr;
5051+
SyStringInitFromBuf(&sStr,SyBlobData(&pEntry->xKey.sKey),SyBlobLength(&pEntry->xKey.sKey));
5052+
PH7_MemObjInitFromString(pSrc->pVm,&sVal,&sStr);
5053+
}
5054+
/* Perform the insertion */
5055+
ph7_array_add_elem(pArray,pKey,&sVal);
5056+
/* Safely release the value because each inserted entry
5057+
* has its own private copy of the value.
5058+
*/
5059+
PH7_MemObjRelease(&sVal);
50355060
}else{
5036-
SyString sStr;
5037-
SyStringInitFromBuf(&sStr,SyBlobData(&pEntry->xKey.sKey),SyBlobLength(&pEntry->xKey.sKey));
5038-
PH7_MemObjInitFromString(pSrc->pVm,&sVal,&sStr);
5061+
/* Unsupported value type -> emit warning and skip the entry */
5062+
PH7_VmThrowError(pCtx->pVm,0,PH7_CTX_WARNING,
5063+
"array_flip(): Can only flip string and integer values, entry skipped"
5064+
);
50395065
}
5040-
/* Perform the insertion */
5041-
ph7_array_add_elem(pArray,pKey,&sVal);
5042-
/* Safely release the value because each inserted entry
5043-
* have it's own private copy of the value.
5044-
*/
5045-
PH7_MemObjRelease(&sVal);
50465066
}
50475067
/* Point to the next entry */
50485068
pEntry = pEntry->pPrev; /* Reverse link */

tests/ph7/001-smoke/function/array_flip/array_flip.phpt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
SPDX-FileCopyrightText: 2025 Alexandre Gomes Gaigalas <alganet@gmail.com>
33
SPDX-License-Identifier: BSD-3-Clause
44
--TEST--
5-
array_flip should swap keys and values; duplicates keep last key
5+
array_flip basic behaviour with duplicate values
66
--FILE--
77
<?php
88
$a = array('a' => 'v1', 'b' => 'v2', 'c' => 'v1');
99
$flip = array_flip($a);
10-
// v1 => 'c' (last), v2 => 'b'
11-
echo ($flip['v1'] === 'c' ? 'ok' : 'fail') . PHP_EOL;
12-
echo ($flip['v2'] === 'b' ? 'ok' : 'fail') . PHP_EOL;
10+
// the earlier and later v1 should leave the last key,
11+
// and v2 should map to 'b'.
12+
$ok = ($flip['v1'] === 'c' && $flip['v2'] === 'b');
13+
echo $ok ? "PASS" : "FAIL";
1314
?>
1415
--EXPECT--
15-
ok
16-
ok
16+
PASS
1717
--CLEAN--
1818
<?php
19-
unset($a, $flip);
19+
unset($a, $flip, $ok);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--CREDITS--
2+
SPDX-FileCopyrightText: 2026 Alexandre Gomes Gaigalas <alganet@gmail.com>
3+
SPDX-License-Identifier: BSD-3-Clause
4+
--TEST--
5+
array_flip should warn and skip sub-array values
6+
--FILE--
7+
<?php
8+
$array = array('a' => array(1,2,3), 'b' => 'ok');
9+
$flipped = array_flip($array);
10+
$pass = (count($flipped) === 1 && isset($flipped['ok']) && $flipped['ok'] === 'b');
11+
echo $pass ? "PASS" : "FAIL";
12+
?>
13+
--EXPECTF--
14+
Error [2]: array_flip(): Can only flip string and integer values, entry skipped in %s on line %d
15+
PASS
16+
--CLEAN--
17+
<?php
18+
unset($array, $flipped, $pass);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--CREDITS--
2+
SPDX-FileCopyrightText: 2026 Alexandre Gomes Gaigalas <alganet@gmail.com>
3+
SPDX-License-Identifier: BSD-3-Clause
4+
--TEST--
5+
array_flip should warn and skip boolean values
6+
--FILE--
7+
<?php
8+
$array = array('a' => true, 'b' => 'yes');
9+
$flipped = array_flip($array);
10+
$pass = (count($flipped) === 1 && isset($flipped['yes']) && $flipped['yes'] === 'b');
11+
echo $pass ? "PASS" : "FAIL";
12+
?>
13+
--EXPECTF--
14+
Error [2]: array_flip(): Can only flip string and integer values, entry skipped in %s on line %d
15+
PASS
16+
--CLEAN--
17+
<?php
18+
unset($array, $flipped, $pass);

tests/ph7/001-smoke/function/array_flip/array_flip_duplicate_values.phpt

Lines changed: 0 additions & 29 deletions
This file was deleted.

tests/ph7/001-smoke/function/array_flip/array_flip_edge_cases.phpt

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--CREDITS--
2+
SPDX-FileCopyrightText: 2026 Alexandre Gomes Gaigalas <alganet@gmail.com>
3+
SPDX-License-Identifier: BSD-3-Clause
4+
--TEST--
5+
array_flip should warn and skip floating-point values
6+
--FILE--
7+
<?php
8+
$array = array('a' => 3.1415, 'b' => 'pi');
9+
$flipped = array_flip($array);
10+
$pass = (count($flipped) === 1 && isset($flipped['pi']) && $flipped['pi'] === 'b');
11+
echo $pass ? "PASS" : "FAIL";
12+
?>
13+
--EXPECTF--
14+
Error [2]: array_flip(): Can only flip string and integer values, entry skipped in %s on line %d
15+
PASS
16+
--CLEAN--
17+
<?php
18+
unset($array, $flipped, $pass);

tests/ph7/001-smoke/function/array_flip/array_flip_invalid.phpt

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--CREDITS--
2+
SPDX-FileCopyrightText: 2026 Alexandre Gomes Gaigalas <alganet@gmail.com>
3+
SPDX-License-Identifier: BSD-3-Clause
4+
--TEST--
5+
array_flip should warn and skip NULL values
6+
--FILE--
7+
<?php
8+
$array = array('a' => null, 'b' => 'ok');
9+
$flipped = array_flip($array);
10+
// after skipping null we expect only the 'ok' entry
11+
$pass = (count($flipped) === 1 && isset($flipped['ok']) && $flipped['ok'] === 'b');
12+
echo $pass ? "PASS" : "FAIL";
13+
?>
14+
--EXPECTF--
15+
Error [2]: array_flip(): Can only flip string and integer values, entry skipped in %s on line %d
16+
PASS
17+
--CLEAN--
18+
<?php
19+
unset($array, $flipped, $pass);

tests/ph7/001-smoke/function/array_flip/array_flip_object.phpt

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)