mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Support enums in array_unique
Fixes GH-9775 Closes GH-11015
This commit is contained in:
parent
84be9042f9
commit
e8b8341d3d
2
NEWS
2
NEWS
@ -27,6 +27,8 @@ PHP NEWS
|
||||
- Standard:
|
||||
. Fixed bug GH-10990 (mail() throws TypeError after iterating over
|
||||
$additional_headers array by reference). (nielsdos)
|
||||
. Fixed bug GH-9775 (Duplicates returned by array_unique when using enums).
|
||||
(ilutov)
|
||||
|
||||
13 Apr 2023, PHP 8.1.18
|
||||
|
||||
|
56
Zend/tests/gh9775_1.phpt
Normal file
56
Zend/tests/gh9775_1.phpt
Normal file
@ -0,0 +1,56 @@
|
||||
--TEST--
|
||||
GH-9775: Backed enum in array_unique()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
enum Test: string
|
||||
{
|
||||
case AUTHENTICATED = 'authenticated';
|
||||
case COURSES_ADMIN = 'courses.admin';
|
||||
case BUNDLES_ADMIN = 'bundles.admin';
|
||||
case COURSES_REPORTING_ACCESS = 'courses-reporting.access';
|
||||
case B2B_DASHBOARD_ACCESS = 'b2b-dashboard.access';
|
||||
case INSTRUCTORS_ADMIN = 'instructors.admin';
|
||||
case USERS_ADMIN = 'users.admin';
|
||||
case COUPONS_ADMIN = 'coupons.admin';
|
||||
}
|
||||
|
||||
$instructorsAdmin = Test::INSTRUCTORS_ADMIN;
|
||||
|
||||
$data = [
|
||||
Test::COURSES_ADMIN,
|
||||
Test::COURSES_REPORTING_ACCESS,
|
||||
Test::BUNDLES_ADMIN,
|
||||
Test::USERS_ADMIN,
|
||||
Test::B2B_DASHBOARD_ACCESS,
|
||||
Test::B2B_DASHBOARD_ACCESS,
|
||||
Test::INSTRUCTORS_ADMIN,
|
||||
&$instructorsAdmin,
|
||||
Test::COUPONS_ADMIN,
|
||||
Test::AUTHENTICATED,
|
||||
];
|
||||
|
||||
$data = array_unique($data, flags: SORT_REGULAR);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(8) {
|
||||
[0]=>
|
||||
enum(Test::COURSES_ADMIN)
|
||||
[1]=>
|
||||
enum(Test::COURSES_REPORTING_ACCESS)
|
||||
[2]=>
|
||||
enum(Test::BUNDLES_ADMIN)
|
||||
[3]=>
|
||||
enum(Test::USERS_ADMIN)
|
||||
[4]=>
|
||||
enum(Test::B2B_DASHBOARD_ACCESS)
|
||||
[6]=>
|
||||
enum(Test::INSTRUCTORS_ADMIN)
|
||||
[8]=>
|
||||
enum(Test::COUPONS_ADMIN)
|
||||
[9]=>
|
||||
enum(Test::AUTHENTICATED)
|
||||
}
|
56
Zend/tests/gh9775_2.phpt
Normal file
56
Zend/tests/gh9775_2.phpt
Normal file
@ -0,0 +1,56 @@
|
||||
--TEST--
|
||||
GH-9775: Pure enum in array_unique()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
enum Test
|
||||
{
|
||||
case AUTHENTICATED;
|
||||
case COURSES_ADMIN;
|
||||
case BUNDLES_ADMIN;
|
||||
case COURSES_REPORTING_ACCESS;
|
||||
case B2B_DASHBOARD_ACCESS;
|
||||
case INSTRUCTORS_ADMIN;
|
||||
case USERS_ADMIN;
|
||||
case COUPONS_ADMIN;
|
||||
}
|
||||
|
||||
$instructorsAdmin = Test::INSTRUCTORS_ADMIN;
|
||||
|
||||
$data = [
|
||||
Test::COURSES_ADMIN,
|
||||
Test::COURSES_REPORTING_ACCESS,
|
||||
Test::BUNDLES_ADMIN,
|
||||
Test::USERS_ADMIN,
|
||||
Test::B2B_DASHBOARD_ACCESS,
|
||||
Test::B2B_DASHBOARD_ACCESS,
|
||||
Test::INSTRUCTORS_ADMIN,
|
||||
&$instructorsAdmin,
|
||||
Test::COUPONS_ADMIN,
|
||||
Test::AUTHENTICATED,
|
||||
];
|
||||
|
||||
$data = array_unique($data, flags: SORT_REGULAR);
|
||||
|
||||
var_dump($data);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(8) {
|
||||
[0]=>
|
||||
enum(Test::COURSES_ADMIN)
|
||||
[1]=>
|
||||
enum(Test::COURSES_REPORTING_ACCESS)
|
||||
[2]=>
|
||||
enum(Test::BUNDLES_ADMIN)
|
||||
[3]=>
|
||||
enum(Test::USERS_ADMIN)
|
||||
[4]=>
|
||||
enum(Test::B2B_DASHBOARD_ACCESS)
|
||||
[6]=>
|
||||
enum(Test::INSTRUCTORS_ADMIN)
|
||||
[8]=>
|
||||
enum(Test::COUPONS_ADMIN)
|
||||
[9]=>
|
||||
enum(Test::AUTHENTICATED)
|
||||
}
|
@ -345,7 +345,27 @@ static zend_always_inline int php_array_key_compare_string_locale_unstable_i(Buc
|
||||
|
||||
static zend_always_inline int php_array_data_compare_unstable_i(Bucket *f, Bucket *s) /* {{{ */
|
||||
{
|
||||
return zend_compare(&f->val, &s->val);
|
||||
int result = zend_compare(&f->val, &s->val);
|
||||
/* Special enums handling for array_unique. We don't want to add this logic to zend_compare as
|
||||
* that would be observable via comparison operators. */
|
||||
zval *rhs = &s->val;
|
||||
ZVAL_DEREF(rhs);
|
||||
if (UNEXPECTED(Z_TYPE_P(rhs) == IS_OBJECT)
|
||||
&& result == ZEND_UNCOMPARABLE
|
||||
&& (Z_OBJCE_P(rhs)->ce_flags & ZEND_ACC_ENUM)) {
|
||||
zval *lhs = &f->val;
|
||||
ZVAL_DEREF(lhs);
|
||||
if (Z_TYPE_P(lhs) == IS_OBJECT && (Z_OBJCE_P(lhs)->ce_flags & ZEND_ACC_ENUM)) {
|
||||
// Order doesn't matter, we just need to group the same enum values
|
||||
uintptr_t lhs_uintptr = (uintptr_t)Z_OBJ_P(lhs);
|
||||
uintptr_t rhs_uintptr = (uintptr_t)Z_OBJ_P(rhs);
|
||||
return lhs_uintptr == rhs_uintptr ? 0 : (lhs_uintptr < rhs_uintptr ? -1 : 1);
|
||||
} else {
|
||||
// Shift enums to the end of the array
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user