@@ -2045,6 +2045,11 @@ static zend_object *date_object_clone_interval(zend_object *this_ptr) /* {{{ */
2045
2045
php_interval_obj * new_obj = php_interval_obj_from_obj (date_object_new_interval (old_obj -> std .ce ));
2046
2046
2047
2047
zend_objects_clone_members (& new_obj -> std , & old_obj -> std );
2048
+ new_obj -> civil_or_wall = old_obj -> civil_or_wall ;
2049
+ new_obj -> from_string = old_obj -> from_string ;
2050
+ if (old_obj -> date_string ) {
2051
+ new_obj -> date_string = zend_string_copy (old_obj -> date_string );
2052
+ }
2048
2053
new_obj -> initialized = old_obj -> initialized ;
2049
2054
if (old_obj -> diff ) {
2050
2055
new_obj -> diff = timelib_rel_time_clone (old_obj -> diff );
@@ -2061,16 +2066,17 @@ static HashTable *date_object_get_gc_interval(zend_object *object, zval **table,
2061
2066
return zend_std_get_properties (object );
2062
2067
} /* }}} */
2063
2068
2064
- static HashTable * date_object_get_properties_interval ( zend_object * object ) /* {{{ */
2069
+ static void date_interval_object_to_hash ( php_interval_obj * intervalobj , HashTable * props )
2065
2070
{
2066
- HashTable * props ;
2067
2071
zval zv ;
2068
- php_interval_obj * intervalobj ;
2069
2072
2070
- intervalobj = php_interval_obj_from_obj (object );
2071
- props = zend_std_get_properties (object );
2072
- if (!intervalobj -> initialized ) {
2073
- return props ;
2073
+ /* Records whether this is a special relative interval that needs to be recreated from a string */
2074
+ if (intervalobj -> from_string ) {
2075
+ ZVAL_BOOL (& zv , (zend_bool )intervalobj -> from_string );
2076
+ zend_hash_str_update (props , "from_string" , strlen ("from_string" ), & zv );
2077
+ ZVAL_STR_COPY (& zv , intervalobj -> date_string );
2078
+ zend_hash_str_update (props , "date_string" , strlen ("date_string" ), & zv );
2079
+ return ;
2074
2080
}
2075
2081
2076
2082
#define PHP_DATE_INTERVAL_ADD_PROPERTY (n ,f ) \
@@ -2085,20 +2091,31 @@ static HashTable *date_object_get_properties_interval(zend_object *object) /* {{
2085
2091
PHP_DATE_INTERVAL_ADD_PROPERTY ("s" , s );
2086
2092
ZVAL_DOUBLE (& zv , (double )intervalobj -> diff -> us / 1000000.0 );
2087
2093
zend_hash_str_update (props , "f" , sizeof ("f" ) - 1 , & zv );
2088
- PHP_DATE_INTERVAL_ADD_PROPERTY ("weekday" , weekday );
2089
- PHP_DATE_INTERVAL_ADD_PROPERTY ("weekday_behavior" , weekday_behavior );
2090
- PHP_DATE_INTERVAL_ADD_PROPERTY ("first_last_day_of" , first_last_day_of );
2091
2094
PHP_DATE_INTERVAL_ADD_PROPERTY ("invert" , invert );
2092
2095
if (intervalobj -> diff -> days != -99999 ) {
2093
2096
PHP_DATE_INTERVAL_ADD_PROPERTY ("days" , days );
2094
2097
} else {
2095
2098
ZVAL_FALSE (& zv );
2096
2099
zend_hash_str_update (props , "days" , sizeof ("days" )- 1 , & zv );
2097
2100
}
2098
- PHP_DATE_INTERVAL_ADD_PROPERTY ("special_type" , special .type );
2099
- PHP_DATE_INTERVAL_ADD_PROPERTY ("special_amount" , special .amount );
2100
- PHP_DATE_INTERVAL_ADD_PROPERTY ("have_weekday_relative" , have_weekday_relative );
2101
- PHP_DATE_INTERVAL_ADD_PROPERTY ("have_special_relative" , have_special_relative );
2101
+ ZVAL_BOOL (& zv , (zend_bool )intervalobj -> from_string );
2102
+ zend_hash_str_update (props , "from_string" , strlen ("from_string" ), & zv );
2103
+
2104
+ #undef PHP_DATE_INTERVAL_ADD_PROPERTY
2105
+ }
2106
+
2107
+ static HashTable * date_object_get_properties_interval (zend_object * object ) /* {{{ */
2108
+ {
2109
+ HashTable * props ;
2110
+ php_interval_obj * intervalobj ;
2111
+
2112
+ intervalobj = php_interval_obj_from_obj (object );
2113
+ props = zend_std_get_properties (object );
2114
+ if (!intervalobj -> initialized ) {
2115
+ return props ;
2116
+ }
2117
+
2118
+ date_interval_object_to_hash (intervalobj , props );
2102
2119
2103
2120
return props ;
2104
2121
} /* }}} */
@@ -2166,6 +2183,10 @@ static void date_object_free_storage_interval(zend_object *object) /* {{{ */
2166
2183
{
2167
2184
php_interval_obj * intern = php_interval_obj_from_obj (object );
2168
2185
2186
+ if (intern -> date_string ) {
2187
+ zend_string_release (intern -> date_string );
2188
+ intern -> date_string = NULL ;
2189
+ }
2169
2190
timelib_rel_time_dtor (intern -> diff );
2170
2191
zend_object_std_dtor (& intern -> std );
2171
2192
} /* }}} */
@@ -3082,7 +3103,7 @@ static void php_date_sub(zval *object, zval *interval, zval *return_value) /* {{
3082
3103
intobj = Z_PHPINTERVAL_P (interval );
3083
3104
DATE_CHECK_INITIALIZED (intobj -> initialized , DateInterval );
3084
3105
3085
- if (intobj -> diff -> have_special_relative ) {
3106
+ if (intobj -> diff -> have_weekday_relative || intobj -> diff -> have_special_relative ) {
3086
3107
php_error_docref (NULL , E_WARNING , "Only non-special relative time specifications are supported for subtraction" );
3087
3108
return ;
3088
3109
}
@@ -4092,6 +4113,41 @@ PHP_METHOD(DateInterval, __construct)
4092
4113
4093
4114
static void php_date_interval_initialize_from_hash (zval * * return_value , php_interval_obj * * intobj , HashTable * myht ) /* {{{ */
4094
4115
{
4116
+ /* If ->diff is already set, then we need to free it first */
4117
+ if ((* intobj )-> diff ) {
4118
+ timelib_rel_time_dtor ((* intobj )-> diff );
4119
+ }
4120
+
4121
+ /* If we have a date_string, use that instead */
4122
+ zval * date_str = zend_hash_str_find (myht , "date_string" , strlen ("date_string" ));
4123
+ if (date_str && Z_TYPE_P (date_str ) == IS_STRING ) {
4124
+ timelib_time * time ;
4125
+ timelib_error_container * err = NULL ;
4126
+
4127
+ time = timelib_strtotime (Z_STRVAL_P (date_str ), Z_STRLEN_P (date_str ), & err , DATE_TIMEZONEDB , php_date_parse_tzfile_wrapper );
4128
+
4129
+ if (err -> error_count > 0 ) {
4130
+ php_error_docref (NULL ,
4131
+ E_WARNING ,
4132
+ "Unknown or bad format (%s) at position %d (%c) while unserializing: %s" ,
4133
+ Z_STRVAL_P (date_str ),
4134
+ err -> error_messages [0 ].position ,
4135
+ err -> error_messages [0 ].character ? err -> error_messages [0 ].character : ' ' , err -> error_messages [0 ].message );
4136
+ }
4137
+
4138
+ (* intobj )-> diff = timelib_rel_time_clone (& time -> relative );
4139
+ (* intobj )-> initialized = 1 ;
4140
+ (* intobj )-> civil_or_wall = PHP_DATE_CIVIL ;
4141
+ (* intobj )-> from_string = true;
4142
+ (* intobj )-> date_string = zend_string_copy (Z_STR_P (date_str ));
4143
+
4144
+ timelib_time_dtor (time );
4145
+ timelib_error_container_dtor (err );
4146
+
4147
+ return ;
4148
+ }
4149
+
4150
+ /* Set new value */
4095
4151
(* intobj )-> diff = timelib_rel_time_ctor ();
4096
4152
4097
4153
#define PHP_DATE_INTERVAL_READ_PROPERTY (element , member , itype , def ) \
@@ -4170,6 +4226,7 @@ static void php_date_interval_initialize_from_hash(zval **return_value, php_inte
4170
4226
(* intobj )-> civil_or_wall = val ;
4171
4227
}
4172
4228
}
4229
+
4173
4230
(* intobj )-> initialized = 1 ;
4174
4231
} /* }}} */
4175
4232
@@ -4192,6 +4249,44 @@ PHP_METHOD(DateInterval, __set_state)
4192
4249
}
4193
4250
/* }}} */
4194
4251
4252
+ /* {{{ */
4253
+ PHP_METHOD (DateInterval , __serialize )
4254
+ {
4255
+ zval * object = ZEND_THIS ;
4256
+ php_interval_obj * intervalobj ;
4257
+ HashTable * myht ;
4258
+
4259
+ ZEND_PARSE_PARAMETERS_NONE ();
4260
+
4261
+ intervalobj = Z_PHPINTERVAL_P (object );
4262
+ DATE_CHECK_INITIALIZED (intervalobj -> initialized , DateInterval );
4263
+
4264
+ array_init (return_value );
4265
+ myht = Z_ARRVAL_P (return_value );
4266
+ date_interval_object_to_hash (intervalobj , myht );
4267
+ }
4268
+ /* }}} */
4269
+
4270
+
4271
+ /* {{{ */
4272
+ PHP_METHOD (DateInterval , __unserialize )
4273
+ {
4274
+ zval * object = ZEND_THIS ;
4275
+ php_interval_obj * intervalobj ;
4276
+ zval * array ;
4277
+ HashTable * myht ;
4278
+
4279
+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
4280
+ Z_PARAM_ARRAY (array )
4281
+ ZEND_PARSE_PARAMETERS_END ();
4282
+
4283
+ intervalobj = Z_PHPINTERVAL_P (object );
4284
+ myht = Z_ARRVAL_P (array );
4285
+
4286
+ php_date_interval_initialize_from_hash (& object , & intervalobj , myht );
4287
+ }
4288
+ /* }}} */
4289
+
4195
4290
/* {{{ */
4196
4291
PHP_METHOD (DateInterval , __wakeup )
4197
4292
{
@@ -4235,6 +4330,8 @@ PHP_FUNCTION(date_interval_create_from_date_string)
4235
4330
diobj -> diff = timelib_rel_time_clone (& time -> relative );
4236
4331
diobj -> initialized = 1 ;
4237
4332
diobj -> civil_or_wall = PHP_DATE_CIVIL ;
4333
+ diobj -> from_string = true;
4334
+ diobj -> date_string = zend_string_copy (time_str );
4238
4335
4239
4336
cleanup :
4240
4337
timelib_time_dtor (time );
0 commit comments