Skip to content

Commit fe88711

Browse files
authored
ext/intl: Use ZPP specifier for IntlTimeZone::createEnumeration() (#19393)
The existing code is extremely convoluted, incorrectly documented, and does not follow the usual semantics
1 parent 140fc69 commit fe88711

File tree

6 files changed

+34
-54
lines changed

6 files changed

+34
-54
lines changed

ext/intl/php_intl.stub.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,8 +571,7 @@ function intltz_count_equivalent_ids(string $timezoneId): int|false {}
571571

572572
function intltz_create_default(): IntlTimeZone {}
573573

574-
/** @param IntlTimeZone|string|int|float|null $countryOrRawOffset */
575-
function intltz_create_enumeration($countryOrRawOffset = null): IntlIterator|false {}
574+
function intltz_create_enumeration(string|int|null $countryOrRawOffset = null): IntlIterator|false {}
576575

577576
function intltz_create_time_zone(string $timezoneId): ?IntlTimeZone {}
578577

ext/intl/php_intl_arginfo.h

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

ext/intl/tests/timezone_createEnumeration_error.phpt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@ IntlTimeZone::createEnumeration(): errors
44
intl
55
--FILE--
66
<?php
7-
ini_set("intl.error_level", E_WARNING);
87

9-
var_dump(IntlTimeZone::createEnumeration(array()));
8+
try {
9+
var_dump(IntlTimeZone::createEnumeration([]));
10+
} catch (Throwable $e) {
11+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
12+
}
13+
14+
try {
15+
var_dump(IntlTimeZone::createEnumeration(new stdClass()));
16+
} catch (Throwable $e) {
17+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
18+
}
1019
?>
11-
--EXPECTF--
12-
Warning: IntlTimeZone::createEnumeration(): invalid argument type in %s on line %d
13-
bool(false)
20+
--EXPECT--
21+
TypeError: IntlTimeZone::createEnumeration(): Argument #1 ($countryOrRawOffset) must be of type string|int|null, array given
22+
TypeError: IntlTimeZone::createEnumeration(): Argument #1 ($countryOrRawOffset) must be of type string|int|null, stdClass given

ext/intl/timezone/timezone.stub.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,10 @@ public static function countEquivalentIDs(string $timezoneId): int|false {}
4545
public static function createDefault(): IntlTimeZone {}
4646

4747
/**
48-
* @param IntlTimeZone|string|int|float|null $countryOrRawOffset
4948
* @tentative-return-type
5049
* @alias intltz_create_enumeration
5150
*/
52-
public static function createEnumeration($countryOrRawOffset = null): IntlIterator|false {}
51+
public static function createEnumeration(string|int|null $countryOrRawOffset = null): IntlIterator|false {}
5352

5453
/**
5554
* @tentative-return-type

ext/intl/timezone/timezone_arginfo.h

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

ext/intl/timezone/timezone_methods.cpp

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -125,62 +125,35 @@ U_CFUNC PHP_FUNCTION(intltz_get_unknown)
125125

126126
U_CFUNC PHP_FUNCTION(intltz_create_enumeration)
127127
{
128-
zval *arg = NULL;
129-
StringEnumeration *se = NULL;
130-
intl_error_reset(NULL);
128+
zend_string *timezone = nullptr;
129+
zend_long timezone_shift = 0;
130+
bool is_null = true;
131+
StringEnumeration *se = nullptr;
132+
intl_error_reset(nullptr);
131133

132134
/* double indirection to have the zend engine destroy the new zval that
133135
* results from separation */
134136
ZEND_PARSE_PARAMETERS_START(0, 1)
135137
Z_PARAM_OPTIONAL
136-
Z_PARAM_ZVAL(arg)
138+
Z_PARAM_STR_OR_LONG_OR_NULL(timezone, timezone_shift, is_null)
137139
ZEND_PARSE_PARAMETERS_END();
138140

139-
if (arg == NULL || Z_TYPE_P(arg) == IS_NULL) {
141+
if (is_null) {
140142
se = TimeZone::createEnumeration();
141-
} else if (Z_TYPE_P(arg) == IS_LONG) {
142-
int_offset:
143-
if (UNEXPECTED(Z_LVAL_P(arg) < (zend_long)INT32_MIN ||
144-
Z_LVAL_P(arg) > (zend_long)INT32_MAX)) {
145-
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
146-
"value is out of range");
147-
RETURN_FALSE;
148-
} else {
149-
se = TimeZone::createEnumeration((int32_t) Z_LVAL_P(arg));
150-
}
151-
} else if (Z_TYPE_P(arg) == IS_DOUBLE) {
152-
double_offset:
153-
convert_to_long(arg);
154-
goto int_offset;
155-
} else if (Z_TYPE_P(arg) == IS_OBJECT || Z_TYPE_P(arg) == IS_STRING) {
156-
zend_long lval;
157-
double dval;
158-
if (!try_convert_to_string(arg)) {
143+
} else if (timezone != nullptr) {
144+
se = TimeZone::createEnumeration(ZSTR_VAL(timezone));
145+
} else {
146+
if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(timezone_shift))) {
147+
zend_argument_value_error(1, "must be between %d and %d", INT32_MIN, INT32_MAX);
159148
RETURN_THROWS();
160149
}
161-
switch (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &lval, &dval, 0)) {
162-
case IS_DOUBLE:
163-
zval_ptr_dtor(arg);
164-
ZVAL_DOUBLE(arg, dval);
165-
goto double_offset;
166-
case IS_LONG:
167-
zval_ptr_dtor(arg);
168-
ZVAL_LONG(arg, lval);
169-
goto int_offset;
170-
}
171-
/* else call string version */
172-
se = TimeZone::createEnumeration(Z_STRVAL_P(arg));
173-
} else {
174-
// TODO Should be a TypeError
175-
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
176-
"invalid argument type");
177-
RETURN_FALSE;
150+
se = TimeZone::createEnumeration(static_cast<int32_t>(timezone_shift));
178151
}
179152

180153
if (se) {
181154
IntlIterator_from_StringEnumeration(se, return_value);
182155
} else {
183-
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
156+
intl_error_set(nullptr, U_ILLEGAL_ARGUMENT_ERROR,
184157
"error obtaining enumeration");
185158
RETVAL_FALSE;
186159
}

0 commit comments

Comments
 (0)