diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 3293e1ad5998a..0b1a8fa106b71 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -360,10 +360,12 @@ static int date_interval_compare_objects(zval *o1, zval *o2); static zval *date_interval_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv); static zval *date_interval_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot); static zval *date_interval_get_property_ptr_ptr(zend_object *object, zend_string *member, int type, void **cache_slot); +static int date_period_has_property(zend_object *object, zend_string *name, int type, void **cache_slot); static zval *date_period_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv); static zval *date_period_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot); static zval *date_period_get_property_ptr_ptr(zend_object *object, zend_string *name, int type, void **cache_slot); - +static void date_period_unset_property(zend_object *object, zend_string *name, void **cache_slot); +static HashTable *date_period_get_properties_for(zend_object *object, zend_prop_purpose purpose); static int date_object_compare_timezone(zval *tz1, zval *tz2); /* {{{ Module struct */ @@ -1505,45 +1507,6 @@ static void create_date_period_interval(timelib_rel_time *interval, zval *zv) } } -static void write_date_period_property(zend_object *obj, const char *name, const size_t name_len, zval *zv) -{ - zend_string *property_name = zend_string_init(name, name_len, 0); - - zend_std_write_property(obj, property_name, zv, NULL); - - zval_ptr_dtor(zv); - zend_string_release(property_name); -} - -static void initialize_date_period_properties(php_period_obj *period_obj) -{ - zval zv; - - /* rebuild properties */ - zend_std_get_properties_ex(&period_obj->std); - - create_date_period_datetime(period_obj->start, period_obj->start_ce, &zv); - write_date_period_property(&period_obj->std, "start", sizeof("start") - 1, &zv); - - create_date_period_datetime(period_obj->current, period_obj->start_ce, &zv); - write_date_period_property(&period_obj->std, "current", sizeof("current") - 1, &zv); - - create_date_period_datetime(period_obj->end, period_obj->start_ce, &zv); - write_date_period_property(&period_obj->std, "end", sizeof("end") - 1, &zv); - - create_date_period_interval(period_obj->interval, &zv); - write_date_period_property(&period_obj->std, "interval", sizeof("interval") - 1, &zv); - - ZVAL_LONG(&zv, (zend_long) period_obj->recurrences); - write_date_period_property(&period_obj->std, "recurrences", sizeof("recurrences") - 1, &zv); - - ZVAL_BOOL(&zv, period_obj->include_start_date); - write_date_period_property(&period_obj->std, "include_start_date", sizeof("include_start_date") - 1, &zv); - - ZVAL_BOOL(&zv, period_obj->include_end_date); - write_date_period_property(&period_obj->std, "include_end_date", sizeof("include_end_date") - 1, &zv); -} - /* define an overloaded iterator structure */ typedef struct { zend_object_iterator intern; @@ -1663,10 +1626,7 @@ static void date_period_it_move_forward(zend_object_iterator *iter) zend_std_get_properties_ex(&object->std); create_date_period_datetime(object->current, object->start_ce, ¤t_zv); - zend_string *property_name = ZSTR_INIT_LITERAL("current", 0); - zend_std_write_property(&object->std, property_name, ¤t_zv, NULL); zval_ptr_dtor(¤t_zv); - zend_string_release(property_name); iterator->current_index++; date_period_it_invalidate_current(iter); @@ -1837,8 +1797,11 @@ static void date_register_classes(void) /* {{{ */ date_object_handlers_period.clone_obj = date_object_clone_period; date_object_handlers_period.get_gc = date_object_get_gc_period; date_object_handlers_period.get_property_ptr_ptr = date_period_get_property_ptr_ptr; + date_object_handlers_period.has_property = date_period_has_property; date_object_handlers_period.read_property = date_period_read_property; date_object_handlers_period.write_property = date_period_write_property; + date_object_handlers_period.get_properties_for = date_period_get_properties_for; + date_object_handlers_period.unset_property = date_period_unset_property; date_ce_date_error = register_class_DateError(zend_ce_error); date_ce_date_object_error = register_class_DateObjectError(date_ce_date_error); @@ -5138,8 +5101,6 @@ static bool date_period_init_finish(php_period_obj *dpobj, zend_long options, ze dpobj->initialized = 1; - initialize_date_period_properties(dpobj); - return true; } @@ -5843,8 +5804,6 @@ static bool php_date_period_initialize_from_hash(php_period_obj *period_obj, Has period_obj->initialized = 1; - initialize_date_period_properties(period_obj); - return 1; } /* }}} */ @@ -5964,14 +5923,84 @@ PHP_METHOD(DatePeriod, __wakeup) zend_throw_error(NULL, "Invalid serialization data for DatePeriod object"); RETURN_THROWS(); } + + restore_custom_dateperiod_properties(object, myht); } /* }}} */ +static int date_period_has_property(zend_object *object, zend_string *name, int type, void **cache_slot) +{ + zval rv; + zval *prop; + + if (!date_period_is_internal_property(name)) { + return zend_std_has_property(object, name, type, cache_slot); + } + + php_period_obj *period_obj = php_period_obj_from_obj(object); + if (!period_obj->initialized) { + switch (type) { + case ZEND_PROPERTY_ISSET: /* Intentional fallthrough */ + case ZEND_PROPERTY_NOT_EMPTY: + return 0; + case ZEND_PROPERTY_EXISTS: + return 1; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + + if (type == ZEND_PROPERTY_EXISTS) { + return 1; + } + + prop = date_period_read_property(object, name, BP_VAR_IS, cache_slot, &rv); + ZEND_ASSERT(prop != &EG(uninitialized_zval)); + + bool result; + + if (type == ZEND_PROPERTY_NOT_EMPTY) { + result = zend_is_true(prop); + } else if (type == ZEND_PROPERTY_ISSET) { + result = Z_TYPE_P(prop) != IS_NULL; + } else { + ZEND_UNREACHABLE(); + } + + zval_ptr_dtor(prop); + + return result; +} + /* {{{ date_period_read_property */ static zval *date_period_read_property(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv) { - if (type != BP_VAR_IS && type != BP_VAR_R) { - if (date_period_is_internal_property(name)) { + if (date_period_is_internal_property(name)) { + if (type == BP_VAR_IS || type == BP_VAR_R) { + php_period_obj *period_obj = php_period_obj_from_obj(object); + + if (zend_string_equals_literal(name, "start")) { + create_date_period_datetime(period_obj->start, period_obj->start_ce, rv); + return rv; + } else if (zend_string_equals_literal(name, "current")) { + create_date_period_datetime(period_obj->current, period_obj->start_ce, rv); + return rv; + } else if (zend_string_equals_literal(name, "end")) { + create_date_period_datetime(period_obj->end, period_obj->start_ce, rv); + return rv; + } else if (zend_string_equals_literal(name, "interval")) { + create_date_period_interval(period_obj->interval, rv); + return rv; + } else if (zend_string_equals_literal(name, "recurrences")) { + ZVAL_LONG(rv, period_obj->recurrences); + return rv; + } else if (zend_string_equals_literal(name, "include_start_date")) { + ZVAL_BOOL(rv, period_obj->include_start_date); + return rv; + } else if (zend_string_equals_literal(name, "include_end_date")) { + ZVAL_BOOL(rv, period_obj->include_end_date); + return rv; + } + } else { zend_readonly_property_modification_error_ex("DatePeriod", ZSTR_VAL(name)); return &EG(uninitialized_zval); } @@ -6000,3 +6029,26 @@ static zval *date_period_get_property_ptr_ptr(zend_object *object, zend_string * return zend_std_get_property_ptr_ptr(object, name, type, cache_slot); } + +static HashTable *date_period_get_properties_for(zend_object *object, zend_prop_purpose purpose) +{ + php_period_obj *period_obj = php_period_obj_from_obj(object); + HashTable *props = zend_array_dup(zend_std_get_properties(object)); + if (!period_obj->initialized) { + return props; + } + + date_period_object_to_hash(period_obj, props); + + return props; +} + +static void date_period_unset_property(zend_object *object, zend_string *name, void **cache_slot) +{ + if (date_period_is_internal_property(name)) { + zend_throw_error(NULL, "Cannot unset %s::$%s", ZSTR_VAL(object->ce->name), ZSTR_VAL(name)); + return; + } + + zend_std_unset_property(object, name, cache_slot); +} diff --git a/ext/date/php_date.stub.php b/ext/date/php_date.stub.php index e18221e712a5d..d0119aac88ad5 100644 --- a/ext/date/php_date.stub.php +++ b/ext/date/php_date.stub.php @@ -673,19 +673,40 @@ class DatePeriod implements IteratorAggregate /** @cvalue PHP_DATE_PERIOD_INCLUDE_END_DATE */ public const int INCLUDE_END_DATE = UNKNOWN; - /** @readonly */ + /** + * @readonly + * @virtual + */ public ?DateTimeInterface $start; - /** @readonly */ + /** + * @readonly + * @virtual + */ public ?DateTimeInterface $current; - /** @readonly */ + /** + * @readonly + * @virtual + */ public ?DateTimeInterface $end; - /** @readonly */ + /** + * @readonly + * @virtual + */ public ?DateInterval $interval; - /** @readonly */ + /** + * @readonly + * @virtual + */ public int $recurrences; - /** @readonly */ + /** + * @readonly + * @virtual + */ public bool $include_start_date; - /** @readonly */ + /** + * @readonly + * @virtual + */ public bool $include_end_date; public static function createFromISO8601String(string $specification, int $options = 0): static {} diff --git a/ext/date/php_date_arginfo.h b/ext/date/php_date_arginfo.h index 8f26db6302345..8ce0114206cfe 100644 --- a/ext/date/php_date_arginfo.h +++ b/ext/date/php_date_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 41c7662745d19808dd4550b37cd1b9f2aa94d75b */ + * Stub hash: d7a318f6fd85e23c6352323e03c323035a511738 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0) @@ -1120,46 +1120,46 @@ static zend_class_entry *register_class_DatePeriod(zend_class_entry *class_entry ZVAL_UNDEF(&property_start_default_value); zend_string *property_start_name = zend_string_init("start", sizeof("start") - 1, 1); zend_string *property_start_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); - zend_declare_typed_property(class_entry, property_start_name, &property_start_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_start_class_DateTimeInterface, 0, MAY_BE_NULL)); + zend_declare_typed_property(class_entry, property_start_name, &property_start_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_start_class_DateTimeInterface, 0, MAY_BE_NULL)); zend_string_release(property_start_name); zval property_current_default_value; ZVAL_UNDEF(&property_current_default_value); zend_string *property_current_name = zend_string_init("current", sizeof("current") - 1, 1); zend_string *property_current_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); - zend_declare_typed_property(class_entry, property_current_name, &property_current_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_current_class_DateTimeInterface, 0, MAY_BE_NULL)); + zend_declare_typed_property(class_entry, property_current_name, &property_current_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_current_class_DateTimeInterface, 0, MAY_BE_NULL)); zend_string_release(property_current_name); zval property_end_default_value; ZVAL_UNDEF(&property_end_default_value); zend_string *property_end_name = zend_string_init("end", sizeof("end") - 1, 1); zend_string *property_end_class_DateTimeInterface = zend_string_init("DateTimeInterface", sizeof("DateTimeInterface")-1, 1); - zend_declare_typed_property(class_entry, property_end_name, &property_end_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_end_class_DateTimeInterface, 0, MAY_BE_NULL)); + zend_declare_typed_property(class_entry, property_end_name, &property_end_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_end_class_DateTimeInterface, 0, MAY_BE_NULL)); zend_string_release(property_end_name); zval property_interval_default_value; ZVAL_UNDEF(&property_interval_default_value); zend_string *property_interval_name = zend_string_init("interval", sizeof("interval") - 1, 1); zend_string *property_interval_class_DateInterval = zend_string_init("DateInterval", sizeof("DateInterval")-1, 1); - zend_declare_typed_property(class_entry, property_interval_name, &property_interval_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_interval_class_DateInterval, 0, MAY_BE_NULL)); + zend_declare_typed_property(class_entry, property_interval_name, &property_interval_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_interval_class_DateInterval, 0, MAY_BE_NULL)); zend_string_release(property_interval_name); zval property_recurrences_default_value; ZVAL_UNDEF(&property_recurrences_default_value); zend_string *property_recurrences_name = zend_string_init("recurrences", sizeof("recurrences") - 1, 1); - zend_declare_typed_property(class_entry, property_recurrences_name, &property_recurrences_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_declare_typed_property(class_entry, property_recurrences_name, &property_recurrences_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(property_recurrences_name); zval property_include_start_date_default_value; ZVAL_UNDEF(&property_include_start_date_default_value); zend_string *property_include_start_date_name = zend_string_init("include_start_date", sizeof("include_start_date") - 1, 1); - zend_declare_typed_property(class_entry, property_include_start_date_name, &property_include_start_date_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); + zend_declare_typed_property(class_entry, property_include_start_date_name, &property_include_start_date_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_include_start_date_name); zval property_include_end_date_default_value; ZVAL_UNDEF(&property_include_end_date_default_value); zend_string *property_include_end_date_name = zend_string_init("include_end_date", sizeof("include_end_date") - 1, 1); - zend_declare_typed_property(class_entry, property_include_end_date_name, &property_include_end_date_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); + zend_declare_typed_property(class_entry, property_include_end_date_name, &property_include_end_date_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_VIRTUAL, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL)); zend_string_release(property_include_end_date_name); return class_entry; diff --git a/ext/date/tests/date_period_is_property.phpt b/ext/date/tests/date_period_is_property.phpt new file mode 100644 index 0000000000000..6ed5e88ae89ef --- /dev/null +++ b/ext/date/tests/date_period_is_property.phpt @@ -0,0 +1,42 @@ +--TEST-- +Test isset on DatePeriod instantiated without its constructor +--FILE-- +newInstanceWithoutConstructor(); + +var_dump(isset($di->start)); +var_dump(empty($di->start)); +var_dump(property_exists($di, "start")); + +var_dump(isset($di->recurrences)); +var_dump(empty($di->recurrences)); +var_dump(property_exists($di, "recurrences")); + +var_dump(isset($di->end)); +var_dump(empty($di->end)); +var_dump(property_exists($di, "end")); + +var_dump(isset($di->my)); +var_dump(empty($di->my)); +var_dump(property_exists($di, "my")); + +?> +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(true) +bool(true) diff --git a/ext/date/tests/date_period_properties.phpt b/ext/date/tests/date_period_properties.phpt new file mode 100644 index 0000000000000..150677ca71e4e --- /dev/null +++ b/ext/date/tests/date_period_properties.phpt @@ -0,0 +1,187 @@ +--TEST-- +Test different usages of DatePeriod properties +--FILE-- + +--EXPECTF-- +object(MyDatePeriod)#%d (%d) { + ["prop"]=> + int(3) + ["start"]=> + object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#%d (%d) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) + ["include_end_date"]=> + bool(false) +} +string(%d) "{"prop":3,"start":{"date":"2012-07-01 00:00:00.000000","timezone_type":1,"timezone":"+00:00"},"current":null,"end":null,"interval":{"y":0,"m":0,"d":7,"h":0,"i":0,"s":0,"f":0,"invert":0,"days":false,"from_string":false},"recurrences":5,"include_start_date":true,"include_end_date":false}" +string(%d) "O:12:"MyDatePeriod":8:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2012-07-01 00:00:00.000000";s:13:"timezone_type";i:1;s:8:"timezone";s:6:"+00:00";}s:7:"current";N;s:3:"end";N;s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:7;s:1:"h";i:0;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:5;s:18:"include_start_date";b:1;s:16:"include_end_date";b:0;s:4:"prop";i:3;}" +array(%d) { + ["prop"]=> + int(3) + ["start"]=> + object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#%d (%d) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) + ["include_end_date"]=> + bool(false) +} +\MyDatePeriod::__set_state(array( + 'prop' => 3, + 'start' => + \DateTimeImmutable::__set_state(array( + 'date' => '2012-07-01 00:00:00.000000', + 'timezone_type' => 1, + 'timezone' => '+00:00', + )), + 'current' => NULL, + 'end' => NULL, + 'interval' => + \DateInterval::__set_state(array( + 'y' => 0, + 'm' => 0, + 'd' => 7, + 'h' => 0, + 'i' => 0, + 's' => 0, + 'f' => 0.0, + 'invert' => 0, + 'days' => false, + 'from_string' => false, + )), + 'recurrences' => 5, + 'include_start_date' => true, + 'include_end_date' => false, +))NULL +array(%d) { + ["prop"]=> + int(3) + ["start"]=> + object(DateTimeImmutable)#%d (%d) { + ["date"]=> + string(26) "2012-07-01 00:00:00.000000" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+00:00" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#%d (%d) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(7) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["f"]=> + float(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["from_string"]=> + bool(false) + } + ["recurrences"]=> + int(5) + ["include_start_date"]=> + bool(true) + ["include_end_date"]=> + bool(false) +} diff --git a/ext/date/tests/date_period_unserialize3.phpt b/ext/date/tests/date_period_unserialize3.phpt index d5d4a57456d9a..4570e3de631fc 100644 --- a/ext/date/tests/date_period_unserialize3.phpt +++ b/ext/date/tests/date_period_unserialize3.phpt @@ -11,9 +11,9 @@ $period = new DatePeriod($start, $interval, $end); try { $period->__unserialize( [ - "current" => new DateTime, - "start" => new DateTime, - "end" => new DateTime, + "current" => new DateTime("2024-08-27 00:00:00"), + "start" => new DateTime("2024-08-28 00:00:00"), + "end" => new DateTime("2024-08-29 00:00:00"), "interval" => new DateInterval('P2D'), "recurrences" => 2, "include_start_date" => "wrong type", @@ -33,18 +33,25 @@ object(DatePeriod)#%d (%d) { ["start"]=> object(DateTime)#%d (%d) { ["date"]=> - string(26) "2022-07-14 00:00:00.000000" + string(26) "2024-08-28 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } ["current"]=> - NULL + object(DateTime)#%d (%d) { + ["date"]=> + string(26) "2024-08-27 00:00:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } ["end"]=> object(DateTime)#%d (%d) { ["date"]=> - string(26) "2022-07-16 00:00:00.000000" + string(26) "2024-08-29 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> @@ -57,7 +64,7 @@ object(DatePeriod)#%d (%d) { ["m"]=> int(0) ["d"]=> - int(1) + int(2) ["h"]=> int(0) ["i"]=> @@ -74,7 +81,7 @@ object(DatePeriod)#%d (%d) { bool(false) } ["recurrences"]=> - int(1) + int(2) ["include_start_date"]=> bool(true) ["include_end_date"]=> diff --git a/ext/date/tests/date_period_unset_property.phpt b/ext/date/tests/date_period_unset_property.phpt new file mode 100644 index 0000000000000..7948d61d268d6 --- /dev/null +++ b/ext/date/tests/date_period_unset_property.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test unsetting DatePeriod properties +--FILE-- +prop); + +try { + $period->prop; +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->start); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->current); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->end); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->interval); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->recurrences); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->include_start_date); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + unset($period->include_end_date); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Typed property MyDatePeriod::$prop must not be accessed before initialization +Cannot unset MyDatePeriod::$start +Cannot unset MyDatePeriod::$current +Cannot unset MyDatePeriod::$end +Cannot unset MyDatePeriod::$interval +Cannot unset MyDatePeriod::$recurrences +Cannot unset MyDatePeriod::$include_start_date +Cannot unset MyDatePeriod::$include_end_date diff --git a/ext/date/tests/gh10747-4.phpt b/ext/date/tests/gh10747-4.phpt index 9933902a498d8..5bd6c3813505d 100644 --- a/ext/date/tests/gh10747-4.phpt +++ b/ext/date/tests/gh10747-4.phpt @@ -26,9 +26,17 @@ $u = unserialize($s); var_dump($i, str_replace(chr(0), '!', $s), $u); ?> --EXPECTF-- -object(I)#1 (11) { +object(I)#%d (%d) { + ["var1":"I":private]=> + int(1) + ["var2":"I":private]=> + int(2) + ["var3":protected]=> + int(3) + ["var4":protected]=> + int(4) ["start"]=> - object(DateTimeImmutable)#5 (3) { + object(DateTimeImmutable)#%d (%d) { ["date"]=> string(26) "2023-03-03 16:24:00.000000" ["timezone_type"]=> @@ -39,7 +47,7 @@ object(I)#1 (11) { ["current"]=> NULL ["end"]=> - object(DateTimeImmutable)#6 (3) { + object(DateTimeImmutable)#%d (%d) { ["date"]=> string(26) "2023-03-09 16:24:00.000000" ["timezone_type"]=> @@ -48,7 +56,7 @@ object(I)#1 (11) { string(3) "UTC" } ["interval"]=> - object(DateInterval)#7 (10) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -76,6 +84,9 @@ object(I)#1 (11) { bool(true) ["include_end_date"]=> bool(false) +} +string(631) "O:1:"I":11:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2023-03-03 16:24:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}s:7:"current";N;s:3:"end";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2023-03-09 16:24:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:1;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:1;s:18:"include_start_date";b:1;s:16:"include_end_date";b:0;s:7:"!I!var1";i:1;s:7:"!I!var2";i:2;s:7:"!*!var3";i:3;s:7:"!*!var4";i:4;}" +object(I)#%d (%d) { ["var1":"I":private]=> int(1) ["var2":"I":private]=> @@ -84,11 +95,8 @@ object(I)#1 (11) { int(3) ["var4":protected]=> int(4) -} -string(631) "O:1:"I":11:{s:5:"start";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2023-03-03 16:24:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}s:7:"current";N;s:3:"end";O:17:"DateTimeImmutable":3:{s:4:"date";s:26:"2023-03-09 16:24:00.000000";s:13:"timezone_type";i:3;s:8:"timezone";s:3:"UTC";}s:8:"interval";O:12:"DateInterval":10:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:1;s:1:"i";i:0;s:1:"s";i:0;s:1:"f";d:0;s:6:"invert";i:0;s:4:"days";b:0;s:11:"from_string";b:0;}s:11:"recurrences";i:1;s:18:"include_start_date";b:1;s:16:"include_end_date";b:0;s:7:"!I!var1";i:1;s:7:"!I!var2";i:2;s:7:"!*!var3";i:3;s:7:"!*!var4";i:4;}" -object(I)#2 (11) { ["start"]=> - object(DateTimeImmutable)#9 (3) { + object(DateTimeImmutable)#%d (%d) { ["date"]=> string(26) "2023-03-03 16:24:00.000000" ["timezone_type"]=> @@ -99,7 +107,7 @@ object(I)#2 (11) { ["current"]=> NULL ["end"]=> - object(DateTimeImmutable)#10 (3) { + object(DateTimeImmutable)#%d (%d) { ["date"]=> string(26) "2023-03-09 16:24:00.000000" ["timezone_type"]=> @@ -108,7 +116,7 @@ object(I)#2 (11) { string(3) "UTC" } ["interval"]=> - object(DateInterval)#11 (10) { + object(DateInterval)#%d (%d) { ["y"]=> int(0) ["m"]=> @@ -136,12 +144,4 @@ object(I)#2 (11) { bool(true) ["include_end_date"]=> bool(false) - ["var1":"I":private]=> - int(1) - ["var2":"I":private]=> - int(2) - ["var3":protected]=> - int(3) - ["var4":protected]=> - int(4) }