mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Bug 54567 DateTimeZone serialize/unserialize
Make DateTimeZone serializable and implement __set_state
This commit is contained in:
parent
5dd73b9e54
commit
30d0ae42b5
@ -500,6 +500,8 @@ const zend_function_entry date_funcs_immutable[] = {
|
||||
|
||||
const zend_function_entry date_funcs_timezone[] = {
|
||||
PHP_ME(DateTimeZone, __construct, arginfo_timezone_open, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
|
||||
PHP_ME(DateTimeZone, __wakeup, NULL, ZEND_ACC_PUBLIC)
|
||||
PHP_ME(DateTimeZone, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
|
||||
PHP_ME_MAPPING(getName, timezone_name_get, arginfo_timezone_method_name_get, 0)
|
||||
PHP_ME_MAPPING(getOffset, timezone_offset_get, arginfo_timezone_method_offset_get, 0)
|
||||
PHP_ME_MAPPING(getTransitions, timezone_transitions_get, arginfo_timezone_method_transitions_get, 0)
|
||||
@ -630,6 +632,7 @@ static HashTable *date_object_get_gc_interval(zval *object, zval ***table, int *
|
||||
static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC);
|
||||
static HashTable *date_object_get_gc_period(zval *object, zval ***table, int *n TSRMLS_DC);
|
||||
static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC);
|
||||
static HashTable *date_object_get_properties_timezone(zval *object TSRMLS_DC);
|
||||
|
||||
zval *date_interval_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC);
|
||||
void date_interval_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC);
|
||||
@ -2017,6 +2020,7 @@ static void date_register_classes(TSRMLS_D)
|
||||
date_ce_timezone = zend_register_internal_class_ex(&ce_timezone, NULL, NULL TSRMLS_CC);
|
||||
memcpy(&date_object_handlers_timezone, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
||||
date_object_handlers_timezone.clone_obj = date_object_clone_timezone;
|
||||
date_object_handlers_timezone.get_properties = date_object_get_properties_timezone;
|
||||
|
||||
#define REGISTER_TIMEZONE_CLASS_CONST_STRING(const_name, value) \
|
||||
zend_declare_class_constant_long(date_ce_timezone, const_name, sizeof(const_name)-1, value TSRMLS_CC);
|
||||
@ -2269,6 +2273,50 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC)
|
||||
return new_ov;
|
||||
}
|
||||
|
||||
static HashTable *date_object_get_properties_timezone(zval *object TSRMLS_DC)
|
||||
{
|
||||
HashTable *props;
|
||||
zval *zv;
|
||||
php_timezone_obj *tzobj;
|
||||
|
||||
|
||||
tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
props = zend_std_get_properties(object TSRMLS_CC);
|
||||
|
||||
if (!tzobj->initialized || GC_G(gc_active)) {
|
||||
return props;
|
||||
}
|
||||
|
||||
MAKE_STD_ZVAL(zv);
|
||||
ZVAL_LONG(zv, tzobj->type);
|
||||
zend_hash_update(props, "timezone_type", 14, &zv, sizeof(zval), NULL);
|
||||
|
||||
MAKE_STD_ZVAL(zv);
|
||||
switch (tzobj->type) {
|
||||
case TIMELIB_ZONETYPE_ID:
|
||||
ZVAL_STRING(zv, tzobj->tzi.tz->name, 1);
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_OFFSET: {
|
||||
char *tmpstr = emalloc(sizeof("UTC+05:00"));
|
||||
|
||||
snprintf(tmpstr, sizeof("+05:00"), "%c%02d:%02d",
|
||||
tzobj->tzi.z.utc_offset > 0 ? '-' : '+',
|
||||
abs(tzobj->tzi.z.utc_offset / 60),
|
||||
abs((tzobj->tzi.z.utc_offset % 60)));
|
||||
|
||||
ZVAL_STRING(zv, tmpstr, 0);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_ABBR:
|
||||
ZVAL_STRING(zv, tzobj->tzi.tz->timezone_abbr, 1);
|
||||
break;
|
||||
}
|
||||
zend_hash_update(props, "timezone", 9, &zv, sizeof(zval), NULL);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
static inline zend_object_value date_object_new_interval_ex(zend_class_entry *class_type, php_interval_obj **ptr TSRMLS_DC)
|
||||
{
|
||||
php_interval_obj *intern;
|
||||
@ -3643,6 +3691,73 @@ PHP_METHOD(DateTimeZone, __construct)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int php_date_timezone_initialize_from_hash(zval **return_value, php_timezone_obj **tzobj, HashTable *myht TSRMLS_DC)
|
||||
{
|
||||
zval **z_timezone = NULL;
|
||||
zval **z_timezone_type = NULL;
|
||||
timelib_tzinfo *tzi;
|
||||
|
||||
if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) {
|
||||
if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) {
|
||||
convert_to_long(*z_timezone_type);
|
||||
switch (Z_LVAL_PP(z_timezone_type)) {
|
||||
case TIMELIB_ZONETYPE_OFFSET:
|
||||
(*tzobj)->type = TIMELIB_ZONETYPE_OFFSET;
|
||||
(*tzobj)->tzi.utc_offset = Z_LVAL_PP(z_timezone);
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_ABBR:
|
||||
(*tzobj)->type = TIMELIB_ZONETYPE_ABBR;
|
||||
(*tzobj)->tzi.z.utc_offset = Z_LVAL_PP(z_timezone);
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_ID:
|
||||
if (SUCCESS == timezone_initialize(&tzi, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) {
|
||||
(*tzobj)->type = TIMELIB_ZONETYPE_ID;
|
||||
(*tzobj)->tzi.tz = tzi;
|
||||
(*tzobj)->initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* {{{ proto DateTimeZone::__set_state()
|
||||
* */
|
||||
PHP_METHOD(DateTimeZone, __set_state)
|
||||
{
|
||||
php_timezone_obj *tzobj;
|
||||
zval *array;
|
||||
HashTable *myht;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
myht = HASH_OF(array);
|
||||
|
||||
php_date_instantiate(date_ce_timezone, return_value TSRMLS_CC);
|
||||
tzobj = (php_timezone_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
|
||||
php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto DateTimeZone::__wakeup()
|
||||
* */
|
||||
PHP_METHOD(DateTimeZone, __wakeup)
|
||||
{
|
||||
zval *object = getThis();
|
||||
php_timezone_obj *tzobj;
|
||||
HashTable *myht;
|
||||
|
||||
tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
myht = Z_OBJPROP_P(object);
|
||||
|
||||
php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string timezone_name_get(DateTimeZone object)
|
||||
Returns the name of the timezone.
|
||||
*/
|
||||
|
@ -84,6 +84,8 @@ PHP_METHOD(DateTimeImmutable, setISODate);
|
||||
PHP_METHOD(DateTimeImmutable, setTimestamp);
|
||||
|
||||
PHP_METHOD(DateTimeZone, __construct);
|
||||
PHP_METHOD(DateTimeZone, __wakeup);
|
||||
PHP_METHOD(DateTimeZone, __set_state);
|
||||
PHP_FUNCTION(timezone_open);
|
||||
PHP_FUNCTION(timezone_name_get);
|
||||
PHP_FUNCTION(timezone_name_from_abbr);
|
||||
@ -144,6 +146,7 @@ struct _php_timezone_obj {
|
||||
int dst;
|
||||
} z;
|
||||
} tzi;
|
||||
HashTable *props;
|
||||
};
|
||||
|
||||
struct _php_interval_obj {
|
||||
|
@ -26,7 +26,11 @@ object(DateTime)#%d (3) {
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
|
||||
Warning: timezone_offset_get() expects exactly 2 parameters, 0 given in %s on line %d
|
||||
|
@ -29,9 +29,17 @@ if ($clone != $orig) {
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
*** Testing clone on DateTime objects ***
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
TEST PASSED : Objects equal but not indetical
|
||||
===DONE===
|
||||
|
@ -31,19 +31,27 @@ var_dump($d2_clone);
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
*** Testing clone on objects whoose class derived from DateTimeZone class ***
|
||||
object(DateTimeZoneExt1)#%d (2) {
|
||||
object(DateTimeZoneExt1)#%d (4) {
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
string(5) "Hello"
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
object(DateTimeZoneExt1)#%d (2) {
|
||||
object(DateTimeZoneExt1)#%d (4) {
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
string(5) "Hello"
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
object(DateTimeZoneExt2)#%d (4) {
|
||||
object(DateTimeZoneExt2)#%d (6) {
|
||||
["property3"]=>
|
||||
bool(true)
|
||||
["property4"]=>
|
||||
@ -52,8 +60,12 @@ object(DateTimeZoneExt2)#%d (4) {
|
||||
int(99)
|
||||
["property2"]=>
|
||||
string(5) "Hello"
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
object(DateTimeZoneExt2)#%d (4) {
|
||||
object(DateTimeZoneExt2)#%d (6) {
|
||||
["property3"]=>
|
||||
bool(true)
|
||||
["property4"]=>
|
||||
@ -62,5 +74,9 @@ object(DateTimeZoneExt2)#%d (4) {
|
||||
int(99)
|
||||
["property2"]=>
|
||||
string(5) "Hello"
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
===DONE===
|
||||
|
@ -30,11 +30,19 @@ var_dump($d2_clone);
|
||||
*** Testing clone on DateTime objects ***
|
||||
|
||||
-- Create a DateTimeZone object --
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
|
||||
-- Add some properties --
|
||||
object(DateTimeZone)#%d (2) {
|
||||
object(DateTimeZone)#%d (4) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
@ -42,7 +50,11 @@ object(DateTimeZone)#%d (2) {
|
||||
}
|
||||
|
||||
-- clone it --
|
||||
object(DateTimeZone)#%d (2) {
|
||||
object(DateTimeZone)#%d (4) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
@ -50,7 +62,11 @@ object(DateTimeZone)#%d (2) {
|
||||
}
|
||||
|
||||
-- Add some more properties --
|
||||
object(DateTimeZone)#%d (4) {
|
||||
object(DateTimeZone)#%d (6) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
@ -62,7 +78,11 @@ object(DateTimeZone)#%d (4) {
|
||||
}
|
||||
|
||||
-- clone it --
|
||||
object(DateTimeZone)#%d (4) {
|
||||
object(DateTimeZone)#%d (6) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
["property1"]=>
|
||||
int(99)
|
||||
["property2"]=>
|
||||
|
@ -21,10 +21,22 @@ var_dump( new DateTimeZone("America/Los_Angeles") );
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
*** Testing new DateTimeZone() : basic functionality ***
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(19) "America/Los_Angeles"
|
||||
}
|
||||
===DONE===
|
||||
|
@ -18,12 +18,18 @@ var_dump( $tz2->getName() );
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(16) "America/New_York"
|
||||
}
|
||||
string(24) "O:12:"DateTimeZone":0:{}"
|
||||
object(DateTimeZone)#%d (0) {
|
||||
string(88) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:3;s:8:"timezone";s:16:"America/New_York";}"
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(16) "America/New_York"
|
||||
}
|
||||
|
||||
Warning: DateTimeZone::getName(): The DateTimeZone object has not been correctly initialized by its constructor in %s on line %d
|
||||
bool(false)
|
||||
===DONE===
|
||||
string(16) "America/New_York"
|
||||
===DONE===
|
||||
|
@ -26,7 +26,7 @@ object(ReflectionClass)#%d (1) {
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
..and get names of all its methods
|
||||
array(7) {
|
||||
array(9) {
|
||||
[0]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
@ -35,41 +35,55 @@ array(7) {
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[1]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
&object(ReflectionMethod)#3 (2) {
|
||||
["name"]=>
|
||||
string(7) "getName"
|
||||
string(8) "__wakeup"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[2]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
&object(ReflectionMethod)#4 (2) {
|
||||
["name"]=>
|
||||
string(9) "getOffset"
|
||||
string(11) "__set_state"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[3]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(14) "getTransitions"
|
||||
string(7) "getName"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[4]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(11) "getLocation"
|
||||
string(9) "getOffset"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[5]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(17) "listAbbreviations"
|
||||
string(14) "getTransitions"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[6]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(11) "getLocation"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[7]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(17) "listAbbreviations"
|
||||
["class"]=>
|
||||
string(12) "DateTimeZone"
|
||||
}
|
||||
[8]=>
|
||||
&object(ReflectionMethod)#%d (2) {
|
||||
["name"]=>
|
||||
string(15) "listIdentifiers"
|
||||
|
@ -18,10 +18,22 @@ var_dump( timezone_open("America/Los_Angeles") );
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
*** Testing timezone_open() : basic functionality ***
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(3) "UTC"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(13) "Europe/London"
|
||||
}
|
||||
object(DateTimeZone)#%d (0) {
|
||||
object(DateTimeZone)#%d (2) {
|
||||
["timezone_type"]=>
|
||||
int(3)
|
||||
["timezone"]=>
|
||||
string(19) "America/Los_Angeles"
|
||||
}
|
||||
===DONE===
|
Loading…
Reference in New Issue
Block a user