Skip to content

Commit 1e108e9

Browse files
authored
ext/intl: wrap DateTimeZone constructor exception in an IntlException (#19410)
The motivation is two fold: - Userland code that deals with ext/intl can be expected to handle IntlException but not necessarily ext/date exceptions - This removes the possibility of superfluous warnings being emitted by ext/intl when an exception has already been thrown
1 parent 8c5c03e commit 1e108e9

File tree

3 files changed

+44
-43
lines changed

3 files changed

+44
-43
lines changed

ext/intl/tests/calendar_toDateTime_error.phpt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,43 @@ $cal = new IntlGregorianCalendar("Etc/Unknown");
99
try {
1010
var_dump($cal->toDateTime());
1111
} catch (Throwable $e) {
12-
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
12+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
13+
$previous = $e->getPrevious();
14+
echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL;
1315
}
1416

1517
try {
1618
var_dump(intlcal_to_date_time($cal));
1719
} catch (Throwable $e) {
18-
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
20+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
21+
$previous = $e->getPrevious();
22+
echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL;
1923
}
2024

2125
$cal = IntlCalendar::createInstance("Etc/Unknown");
2226
try {
2327
var_dump($cal->toDateTime());
2428
} catch (Throwable $e) {
25-
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
29+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
30+
$previous = $e->getPrevious();
31+
echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL;
2632
}
2733

2834
try {
2935
var_dump(intlcal_to_date_time($cal));
3036
} catch (Throwable $e) {
31-
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
37+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
38+
$previous = $e->getPrevious();
39+
echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL;
3240
}
3341

3442
?>
3543
--EXPECT--
36-
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
37-
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
38-
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
39-
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
44+
IntlException: DateTimeZone constructor threw exception
45+
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
46+
IntlException: DateTimeZone constructor threw exception
47+
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
48+
IntlException: DateTimeZone constructor threw exception
49+
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)
50+
IntlException: DateTimeZone constructor threw exception
51+
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)

ext/intl/tests/timezone_toDateTimeZone_error.phpt

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

98
$tz = IntlTimeZone::createTimeZone('Etc/Unknown');
109

1110
try {
1211
var_dump($tz->toDateTimeZone());
13-
} catch (Exception $e) {
14-
var_dump($e->getMessage());
12+
} catch (Throwable $e) {
13+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
14+
$previous = $e->getPrevious();
15+
echo ' ', $previous::class, ': ', $previous->getMessage(), PHP_EOL;
1516
}
1617

1718
?>
18-
--EXPECTF--
19-
Warning: IntlTimeZone::toDateTimeZone(): DateTimeZone constructor threw exception in %s on line %d
20-
string(66) "DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)"
19+
--EXPECT--
20+
IntlException: DateTimeZone constructor threw exception
21+
DateInvalidTimeZoneException: DateTimeZone::__construct(): Unknown or bad timezone (Etc/Unknown)

ext/intl/timezone/timezone_class.cpp

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,56 +64,44 @@ U_CFUNC zval *timezone_convert_to_datetimezone(const TimeZone *timeZone,
6464
intl_error *outside_error,
6565
zval *ret)
6666
{
67-
UnicodeString id;
68-
php_timezone_obj *tzobj;
69-
zval arg;
67+
UnicodeString id;
7068

7169
timeZone->getID(id);
7270
if (id.isBogus()) {
7371
intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
7472
"could not obtain TimeZone id");
75-
goto error;
73+
return nullptr;
7674
}
7775

78-
object_init_ex(ret, php_date_get_timezone_ce());
79-
tzobj = Z_PHPTIMEZONE_P(ret);
80-
8176
if (id.compare(0, 3, UnicodeString("GMT", sizeof("GMT")-1, US_INV)) == 0) {
8277
/* The DateTimeZone constructor doesn't support offset time zones,
83-
* so we must mess with DateTimeZone structure ourselves */
84-
tzobj->initialized = 1;
78+
* so we must mess with DateTimeZone structure ourselves */
79+
object_init_ex(ret, php_date_get_timezone_ce());
80+
php_timezone_obj *tzobj = Z_PHPTIMEZONE_P(ret);
81+
82+
tzobj->initialized = true;
8583
tzobj->type = TIMELIB_ZONETYPE_OFFSET;
8684
//convert offset from milliseconds to seconds
8785
tzobj->tzi.utc_offset = timeZone->getRawOffset() / 1000;
8886
} else {
89-
zend_string *u8str;
90-
/* Call the constructor! */
91-
u8str = intl_charFromString(id, &INTL_ERROR_CODE(*outside_error));
87+
zend_string *u8str = intl_charFromString(id, &INTL_ERROR_CODE(*outside_error));
9288
if (!u8str) {
9389
intl_errors_set(outside_error, INTL_ERROR_CODE(*outside_error),
9490
"could not convert id to UTF-8");
95-
goto error;
91+
return nullptr;
9692
}
93+
94+
zval arg;
9795
ZVAL_STR(&arg, u8str);
98-
zend_call_known_instance_method_with_1_params(
99-
Z_OBJCE_P(ret)->constructor, Z_OBJ_P(ret), NULL, &arg);
100-
if (EG(exception)) {
101-
intl_errors_set(outside_error, U_ILLEGAL_ARGUMENT_ERROR,
102-
"DateTimeZone constructor threw exception");
103-
zend_object_store_ctor_failed(Z_OBJ_P(ret));
104-
zval_ptr_dtor(&arg);
105-
goto error;
106-
}
96+
/* Instantiate the object and call the constructor */
97+
zend_result status = object_init_with_constructor(ret, php_date_get_timezone_ce(), 1, &arg, nullptr);
10798
zval_ptr_dtor(&arg);
108-
}
109-
110-
if (0) {
111-
error:
112-
if (ret) {
113-
zval_ptr_dtor(ret);
99+
if (UNEXPECTED(status == FAILURE)) {
100+
zend_throw_exception(IntlException_ce_ptr, "DateTimeZone constructor threw exception", 0);
101+
return nullptr;
114102
}
115-
ret = NULL;
116103
}
104+
117105
return ret;
118106
}
119107
/* }}} */

0 commit comments

Comments
 (0)