Skip to content

Commit 81a19ea

Browse files
committed
Add DateTimeZone's __serialize and __unserialize methods
1 parent db826ee commit 81a19ea

File tree

5 files changed

+133
-19
lines changed

5 files changed

+133
-19
lines changed

ext/date/php_date.c

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1954,10 +1954,20 @@ static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv)
19541954
}
19551955
}
19561956

1957+
void date_timezone_object_to_hash(php_timezone_obj *tzobj, HashTable *props)
1958+
{
1959+
zval zv;
1960+
1961+
ZVAL_LONG(&zv, tzobj->type);
1962+
zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
1963+
1964+
php_timezone_to_string(tzobj, &zv);
1965+
zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
1966+
}
1967+
19571968
static HashTable *date_object_get_properties_for_timezone(zend_object *object, zend_prop_purpose purpose) /* {{{ */
19581969
{
19591970
HashTable *props;
1960-
zval zv;
19611971
php_timezone_obj *tzobj;
19621972

19631973
switch (purpose) {
@@ -1977,11 +1987,7 @@ static HashTable *date_object_get_properties_for_timezone(zend_object *object, z
19771987
return props;
19781988
}
19791989

1980-
ZVAL_LONG(&zv, tzobj->type);
1981-
zend_hash_str_update(props, "timezone_type", sizeof("timezone_type")-1, &zv);
1982-
1983-
php_timezone_to_string(tzobj, &zv);
1984-
zend_hash_str_update(props, "timezone", sizeof("timezone")-1, &zv);
1990+
date_timezone_object_to_hash(tzobj, props);
19851991

19861992
return props;
19871993
} /* }}} */
@@ -3489,19 +3495,19 @@ static zend_result timezone_initialize(php_timezone_obj *tzobj, const char *tz,
34893495
if (strlen(tz) != tz_len) {
34903496
php_error_docref(NULL, E_WARNING, "Timezone must not contain null bytes");
34913497
efree(dummy_t);
3492-
return FAILURE;
3498+
return false;
34933499
}
34943500

34953501
dummy_t->z = timelib_parse_zone(&tz, &dst, dummy_t, &not_found, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
34963502
if (not_found) {
34973503
php_error_docref(NULL, E_WARNING, "Unknown or bad timezone (%s)", orig_tz);
34983504
efree(dummy_t);
3499-
return FAILURE;
3505+
return false;
35003506
} else {
35013507
set_timezone_from_timelib_time(tzobj, dummy_t);
35023508
timelib_free(dummy_t->tz_abbr);
35033509
efree(dummy_t);
3504-
return SUCCESS;
3510+
return true;
35053511
}
35063512
} /* }}} */
35073513

@@ -3516,7 +3522,7 @@ PHP_FUNCTION(timezone_open)
35163522
ZEND_PARSE_PARAMETERS_END();
35173523

35183524
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
3519-
if (FAILURE == timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) {
3525+
if (!timezone_initialize(tzobj, ZSTR_VAL(tz), ZSTR_LEN(tz))) {
35203526
zval_ptr_dtor(return_value);
35213527
RETURN_FALSE;
35223528
}
@@ -3546,20 +3552,20 @@ static zend_result php_date_timezone_initialize_from_hash(zval **return_value, p
35463552
zval *z_timezone_type;
35473553

35483554
if ((z_timezone_type = zend_hash_str_find(myht, "timezone_type", sizeof("timezone_type") - 1)) == NULL) {
3549-
return FAILURE;
3555+
return false;
35503556
}
35513557

35523558
zval *z_timezone;
35533559

35543560
if ((z_timezone = zend_hash_str_find(myht, "timezone", sizeof("timezone") - 1)) == NULL) {
3555-
return FAILURE;
3561+
return false;
35563562
}
35573563

35583564
if (Z_TYPE_P(z_timezone_type) != IS_LONG) {
3559-
return FAILURE;
3565+
return false;
35603566
}
35613567
if (Z_TYPE_P(z_timezone) != IS_STRING) {
3562-
return FAILURE;
3568+
return false;
35633569
}
35643570
return timezone_initialize(*tzobj, Z_STRVAL_P(z_timezone), Z_STRLEN_P(z_timezone));
35653571
} /* }}} */
@@ -3579,7 +3585,7 @@ PHP_METHOD(DateTimeZone, __set_state)
35793585

35803586
php_date_instantiate(date_ce_timezone, return_value);
35813587
tzobj = Z_PHPTIMEZONE_P(return_value);
3582-
if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) {
3588+
if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
35833589
zend_throw_error(NULL, "Timezone initialization failed");
35843590
zval_ptr_dtor(return_value);
35853591
}
@@ -3599,12 +3605,50 @@ PHP_METHOD(DateTimeZone, __wakeup)
35993605

36003606
myht = Z_OBJPROP_P(object);
36013607

3602-
if (php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht) == FAILURE) {
3608+
if (!php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht)) {
36033609
zend_throw_error(NULL, "Timezone initialization failed");
36043610
}
36053611
}
36063612
/* }}} */
36073613

3614+
/* {{{ */
3615+
PHP_METHOD(DateTimeZone, __serialize)
3616+
{
3617+
zval *object = ZEND_THIS;
3618+
php_timezone_obj *tzobj;
3619+
HashTable *myht;
3620+
3621+
ZEND_PARSE_PARAMETERS_NONE();
3622+
3623+
tzobj = Z_PHPTIMEZONE_P(object);
3624+
3625+
array_init(return_value);
3626+
myht = Z_ARRVAL_P(return_value);
3627+
date_timezone_object_to_hash(tzobj, myht);
3628+
}
3629+
/* }}} */
3630+
3631+
/* {{{ */
3632+
PHP_METHOD(DateTimeZone, __unserialize)
3633+
{
3634+
zval *object = ZEND_THIS;
3635+
php_timezone_obj *tzobj;
3636+
zval *array;
3637+
HashTable *myht;
3638+
3639+
ZEND_PARSE_PARAMETERS_START(1, 1)
3640+
Z_PARAM_ARRAY(array)
3641+
ZEND_PARSE_PARAMETERS_END();
3642+
3643+
tzobj = Z_PHPTIMEZONE_P(object);
3644+
myht = Z_ARRVAL_P(array);
3645+
3646+
if (!php_date_timezone_initialize_from_hash(&object, &tzobj, myht)) {
3647+
zend_throw_error(NULL, "Invalid serialization data for DateTimeZone object");
3648+
}
3649+
}
3650+
/* }}} */
3651+
36083652
/* {{{ Returns the name of the timezone. */
36093653
PHP_FUNCTION(timezone_name_get)
36103654
{

ext/date/php_date.stub.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ public static function listAbbreviations(): array {}
453453
*/
454454
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {}
455455

456+
public function __serialize(): array {}
457+
458+
public function __unserialize(array $data): void {}
459+
456460
/** @tentative-return-type */
457461
public function __wakeup(): void {}
458462

ext/date/php_date_arginfo.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: ea354510fbf64c42ee1cdd6fd786ab937516226c */
2+
* Stub hash: a157de6bca4bcf5a9ddace9e81ef700f132b4dda */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
55
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
@@ -431,6 +431,10 @@ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_DateTimeZone_lis
431431
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null")
432432
ZEND_END_ARG_INFO()
433433

434+
#define arginfo_class_DateTimeZone___serialize arginfo_timezone_abbreviations_list
435+
436+
#define arginfo_class_DateTimeZone___unserialize arginfo_class_DateTimeInterface___unserialize
437+
434438
#define arginfo_class_DateTimeZone___wakeup arginfo_class_DateTimeInterface___wakeup
435439

436440
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_OBJ_INFO_EX(arginfo_class_DateTimeZone___set_state, 0, 1, DateTimeZone, 0)
@@ -553,6 +557,8 @@ ZEND_METHOD(DateTimeImmutable, setTimestamp);
553557
ZEND_METHOD(DateTimeImmutable, createFromMutable);
554558
ZEND_METHOD(DateTimeImmutable, createFromInterface);
555559
ZEND_METHOD(DateTimeZone, __construct);
560+
ZEND_METHOD(DateTimeZone, __serialize);
561+
ZEND_METHOD(DateTimeZone, __unserialize);
556562
ZEND_METHOD(DateTimeZone, __wakeup);
557563
ZEND_METHOD(DateTimeZone, __set_state);
558564
ZEND_METHOD(DateInterval, __construct);
@@ -696,6 +702,8 @@ static const zend_function_entry class_DateTimeZone_methods[] = {
696702
ZEND_ME_MAPPING(getLocation, timezone_location_get, arginfo_class_DateTimeZone_getLocation, ZEND_ACC_PUBLIC)
697703
ZEND_ME_MAPPING(listAbbreviations, timezone_abbreviations_list, arginfo_class_DateTimeZone_listAbbreviations, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
698704
ZEND_ME_MAPPING(listIdentifiers, timezone_identifiers_list, arginfo_class_DateTimeZone_listIdentifiers, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
705+
ZEND_ME(DateTimeZone, __serialize, arginfo_class_DateTimeZone___serialize, ZEND_ACC_PUBLIC)
706+
ZEND_ME(DateTimeZone, __unserialize, arginfo_class_DateTimeZone___unserialize, ZEND_ACC_PUBLIC)
699707
ZEND_ME(DateTimeZone, __wakeup, arginfo_class_DateTimeZone___wakeup, ZEND_ACC_PUBLIC)
700708
ZEND_ME(DateTimeZone, __set_state, arginfo_class_DateTimeZone___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
701709
ZEND_FE_END
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
Test DateTimeZone::__serialize and DateTime::__unserialize
3+
--FILE--
4+
<?php
5+
$tz = new DateTimeZone("CEST");
6+
var_dump($tz->__serialize());
7+
8+
$tz = new DateTimeZone("UTC");
9+
$tz->__unserialize(
10+
[
11+
'timezone_type' => 3,
12+
'timezone' => 'Europe/London',
13+
]
14+
);
15+
var_dump($tz);
16+
17+
$tz->__unserialize(
18+
[
19+
'timezone_type' => 2,
20+
'timezone' => 'CEST',
21+
]
22+
);
23+
var_dump($tz);
24+
25+
$tz->__unserialize(
26+
[
27+
'timezone_type' => 1,
28+
'timezone' => '+0130',
29+
]
30+
);
31+
var_dump($tz);
32+
33+
?>
34+
--EXPECTF--
35+
array(2) {
36+
["timezone_type"]=>
37+
int(2)
38+
["timezone"]=>
39+
string(4) "CEST"
40+
}
41+
object(DateTimeZone)#%d (%d) {
42+
["timezone_type"]=>
43+
int(3)
44+
["timezone"]=>
45+
string(13) "Europe/London"
46+
}
47+
object(DateTimeZone)#%d (%d) {
48+
["timezone_type"]=>
49+
int(2)
50+
["timezone"]=>
51+
string(4) "CEST"
52+
}
53+
object(DateTimeZone)#%d (%d) {
54+
["timezone_type"]=>
55+
int(1)
56+
["timezone"]=>
57+
string(6) "+01:30"
58+
}

ext/date/tests/bug68942.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ $data = unserialize('a:2:{i:0;O:12:"DateTimeZone":2:{s:13:"timezone_type";a:2:{i
66
var_dump($data);
77
?>
88
--EXPECTF--
9-
Fatal error: Uncaught Error: Timezone initialization failed in %s:%d
9+
Fatal error: Uncaught Error: Invalid serialization data for DateTimeZone object in %s:%d
1010
Stack trace:
11-
#0 [internal function]: DateTimeZone->__wakeup()
11+
#0 [internal function]: DateTimeZone->__unserialize(Array)
1212
#1 %s(%d): unserialize('a:2:{i:0;O:12:"...')
1313
#2 {main}
1414
thrown in %s on line %d

0 commit comments

Comments
 (0)