@@ -44,6 +44,51 @@ static uri_handler_t *uri_handler_by_name(const char *handler_name, size_t handl
4444 return zend_hash_str_find_ptr (& uri_handlers , handler_name , handler_name_len );
4545}
4646
47+ static HashTable * uri_get_properties (zend_object * object , bool is_debug )
48+ {
49+ uri_internal_t * internal_uri = uri_internal_from_obj (object );
50+ ZEND_ASSERT (internal_uri != NULL );
51+ if (UNEXPECTED (internal_uri -> uri == NULL )) {
52+ if (!is_debug ) {
53+ zend_throw_error (NULL , "%s object is not correctly initialized" , ZSTR_VAL (object -> ce -> name ));
54+ }
55+ return NULL ;
56+ }
57+
58+ zend_string * string_key ;
59+ uri_property_handler_t * property_handler ;
60+
61+ HashTable * std_properties = zend_std_get_properties (object );
62+ HashTable * result = zend_array_dup (std_properties );
63+
64+ zend_string * object_str = is_debug ? ZSTR_INIT_LITERAL ("(object value omitted)" , false) : NULL ;
65+
66+ const HashTable * property_handlers = internal_uri -> handler -> property_handlers ;
67+ ZEND_HASH_MAP_FOREACH_STR_KEY_PTR (property_handlers , string_key , property_handler ) {
68+ zval value ;
69+
70+ ZEND_ASSERT (string_key != NULL );
71+
72+ if (property_handler -> read_func (internal_uri , & value ) == FAILURE ) {
73+ continue ;
74+ }
75+
76+ if (is_debug && Z_TYPE (value ) == IS_OBJECT ) {
77+ zval_ptr_dtor (& value );
78+ ZVAL_NEW_STR (& value , object_str );
79+ zend_string_addref (object_str );
80+ }
81+
82+ zend_hash_update (result , string_key , & value );
83+ } ZEND_HASH_FOREACH_END ();
84+
85+ if (is_debug ) {
86+ zend_string_release_ex (object_str , false);
87+ }
88+
89+ return result ;
90+ }
91+
4792PHPAPI uri_handler_t * php_uri_get_handler (const zend_string * uri_handler_name )
4893{
4994 if (uri_handler_name == NULL ) {
@@ -75,7 +120,7 @@ PHPAPI uri_internal_t *php_uri_parse(const uri_handler_t *uri_handler, zend_stri
75120
76121static zend_result php_uri_get_property (const uri_internal_t * internal_uri , zend_string * name , zval * zv )
77122{
78- uri_property_handler_t * property_handler = uri_property_handler_from_uri_handler (internal_uri -> handler , name );
123+ uri_property_handler_t * property_handler = uri_property_handler_from_internal_uri (internal_uri , name );
79124 if (property_handler == NULL ) {
80125 return FAILURE ;
81126 }
@@ -327,6 +372,83 @@ PHP_METHOD(Uri_Rfc3986Uri, __toString)
327372 RETURN_STR (internal_uri -> handler -> uri_to_string (internal_uri -> uri ));
328373}
329374
375+ PHP_METHOD (Uri_Rfc3986Uri , __serialize )
376+ {
377+ ZEND_PARSE_PARAMETERS_NONE ();
378+
379+ zend_object * this_object = Z_OBJ_P (ZEND_THIS );
380+ uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
381+ URI_CHECK_INITIALIZATION_RETURN_THROWS (internal_uri , this_object );
382+
383+ HashTable * ht = uri_get_properties (this_object , false);
384+ ZVAL_ARR (return_value , ht );
385+ }
386+
387+ static void uri_restore_custom_properties (zend_object * object , uri_internal_t * internal_uri , HashTable * ht )
388+ {
389+ zend_string * prop_name ;
390+ zval * prop_val ;
391+
392+ ZEND_HASH_FOREACH_STR_KEY_VAL (ht , prop_name , prop_val ) {
393+ if (!prop_name || Z_TYPE_P (prop_val ) == IS_REFERENCE || uri_property_handler_from_internal_uri (internal_uri , prop_name )) {
394+ continue ;
395+ }
396+
397+ zend_update_property_ex (object -> ce , object , prop_name , prop_val );
398+ if (EG (exception )) {
399+ break ;
400+ }
401+ } ZEND_HASH_FOREACH_END ();
402+ }
403+
404+ PHP_METHOD (Uri_Rfc3986Uri , __unserialize )
405+ {
406+ HashTable * ht ;
407+
408+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
409+ Z_PARAM_ARRAY_HT (ht )
410+ ZEND_PARSE_PARAMETERS_END ();
411+
412+ zend_object * object = Z_OBJ_P (ZEND_THIS );
413+ uri_internal_t * internal_uri = uri_internal_from_obj (object );
414+
415+ /*if (!php_date_initialize_from_hash(&dateobj, myht)) {
416+ zend_throw_error(NULL, "Invalid serialization data for DateTime object");
417+ RETURN_THROWS();
418+ }*/
419+
420+ zend_string * str = zend_string_init ("https://example.com" , sizeof ("https://example.com" ) - 1 , false);
421+
422+ internal_uri -> handler = uri_handler_by_name ("rfc3986" , sizeof ("rfc3986" ) - 1 );
423+ internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , NULL );
424+
425+ uri_restore_custom_properties (object , internal_uri , ht );
426+ }
427+
428+ PHP_METHOD (Uri_WhatWgUri , __unserialize )
429+ {
430+ HashTable * ht ;
431+
432+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
433+ Z_PARAM_ARRAY_HT (ht )
434+ ZEND_PARSE_PARAMETERS_END ();
435+
436+ zend_object * object = Z_OBJ_P (ZEND_THIS );
437+ uri_internal_t * internal_uri = uri_internal_from_obj (object );
438+
439+ /*if (!php_date_initialize_from_hash(&dateobj, myht)) {
440+ zend_throw_error(NULL, "Invalid serialization data for DateTime object");
441+ RETURN_THROWS();
442+ }*/
443+
444+ zend_string * str = zend_string_init ("https://example.com" , sizeof ("https://example.com" ) - 1 , false);
445+
446+ internal_uri -> handler = uri_handler_by_name ("whatwg" , sizeof ("whatwg" ) - 1 );
447+ internal_uri -> uri = internal_uri -> handler -> parse_uri (str , NULL , NULL );
448+
449+ uri_restore_custom_properties (object , internal_uri , ht );
450+ }
451+
330452static zend_object * uri_create_object_handler (zend_class_entry * class_type )
331453{
332454 uri_object_t * uri_object = zend_object_alloc (sizeof (uri_object_t ), class_type );
@@ -366,7 +488,7 @@ static int uri_has_property_handler(zend_object *object, zend_string *name, int
366488 }
367489
368490 uri_property_handler_t * property_handler = zend_hash_find_ptr (internal_uri -> handler -> property_handlers , name );
369- if (! property_handler ) {
491+ if (UNEXPECTED ( property_handler == NULL ) ) {
370492 return zend_std_has_property (object , name , check_empty , cache_slot );
371493 }
372494
@@ -400,7 +522,7 @@ static zval *uri_read_property_handler(zend_object *object, zend_string *name, i
400522 uri_internal_t * internal_uri = uri_internal_from_obj (object );
401523 URI_CHECK_INITIALIZATION_RETURN (internal_uri , object , & EG (uninitialized_zval ));
402524
403- uri_property_handler_t * property_handler = uri_property_handler_from_uri_handler (internal_uri -> handler , name );
525+ uri_property_handler_t * property_handler = uri_property_handler_from_internal_uri (internal_uri , name );
404526 if (UNEXPECTED (property_handler == NULL )) {
405527 return zend_std_read_property (object , name , type , cache_slot , rv );
406528 }
@@ -426,39 +548,38 @@ static zval *uri_write_property_handler(zend_object *object, zend_string *name,
426548 uri_internal_t * internal_uri = uri_internal_from_obj (object );
427549 URI_CHECK_INITIALIZATION_RETURN (internal_uri , object , & EG (error_zval ));
428550
429- uri_property_handler_t * property_handler = uri_property_handler_from_uri_handler (internal_uri -> handler , name );
430- if (UNEXPECTED (property_handler != NULL )) {
431- zend_readonly_property_modification_error_ex (ZSTR_VAL (object -> ce -> name ), ZSTR_VAL (name ));
432- return & EG (error_zval );
551+ uri_property_handler_t * property_handler = uri_property_handler_from_internal_uri (internal_uri , name );
552+ if (UNEXPECTED (property_handler == NULL )) {
553+ return zend_std_write_property (object , name , value , cache_slot );
433554 }
434555
435- return zend_std_write_property (object , name , value , cache_slot );
556+ zend_readonly_property_modification_error_ex (ZSTR_VAL (object -> ce -> name ), ZSTR_VAL (name ));
557+ return & EG (error_zval );
436558}
437559
438560static zval * uri_get_property_ptr_ptr_handler (zend_object * object , zend_string * name , int type , void * * cache_slot )
439561{
440562 const uri_internal_t * internal_uri = uri_internal_from_obj (object );
441563 URI_CHECK_INITIALIZATION_RETURN (internal_uri , object , NULL );
442564
443- if (uri_property_handler_from_uri_handler (internal_uri -> handler , name )) {
444- zend_readonly_property_modification_error_ex (ZSTR_VAL (object -> ce -> name ), ZSTR_VAL (name ));
445- return & EG (error_zval );
565+ if (UNEXPECTED (uri_property_handler_from_internal_uri (internal_uri , name ) == NULL )) {
566+ return zend_std_get_property_ptr_ptr (object , name , type , cache_slot );
446567 }
447568
448- return zend_std_get_property_ptr_ptr (object , name , type , cache_slot );
569+ zend_readonly_property_modification_error_ex (ZSTR_VAL (object -> ce -> name ), ZSTR_VAL (name ));
570+ return & EG (error_zval );
449571}
450572
451573static void uri_unset_property_handler (zend_object * object , zend_string * name , void * * cache_slot )
452574{
453575 uri_internal_t * internal_uri = uri_internal_from_obj (object );
454576 URI_CHECK_INITIALIZATION_RETURN_VOID (internal_uri , object );
455577
456- if (uri_property_handler_from_uri_handler (internal_uri -> handler , name )) {
457- zend_throw_error (NULL , "Cannot unset readonly property %s::$%s" , ZSTR_VAL (object -> ce -> name ), ZSTR_VAL (name ));
458- return ;
578+ if (UNEXPECTED (uri_property_handler_from_internal_uri (internal_uri , name ) == NULL )) {
579+ zend_std_unset_property (object , name , cache_slot );
459580 }
460581
461- zend_std_unset_property ( object , name , cache_slot );
582+ zend_throw_error ( NULL , "Cannot unset readonly property %s::$%s" , ZSTR_VAL ( object -> ce -> name ), ZSTR_VAL ( name ) );
462583}
463584
464585static zend_object * uri_clone_obj_handler (zend_object * object )
@@ -489,46 +610,9 @@ static zend_object *uri_clone_obj_handler(zend_object *object)
489610
490611static HashTable * uri_get_debug_info_handler (zend_object * object , int * is_temp )
491612{
492- HashTable * debug_info , * std_properties ;
493-
494- uri_internal_t * internal_uri = uri_internal_from_obj (object );
495- ZEND_ASSERT (internal_uri != NULL );
496- if (UNEXPECTED (internal_uri -> uri == NULL )) {
497- return NULL ;
498- }
499-
500- const HashTable * property_handlers = internal_uri -> handler -> property_handlers ;
501- zend_string * string_key ;
502- uri_property_handler_t * property_handler ;
503-
504613 * is_temp = 1 ;
505614
506- std_properties = zend_std_get_properties (object );
507- debug_info = zend_array_dup (std_properties );
508-
509- zend_string * object_str = ZSTR_INIT_LITERAL ("(object value omitted)" , false);
510-
511- ZEND_HASH_MAP_FOREACH_STR_KEY_PTR (property_handlers , string_key , property_handler ) {
512- zval value ;
513-
514- ZEND_ASSERT (string_key != NULL );
515-
516- if (property_handler -> read_func (internal_uri , & value ) == FAILURE ) {
517- continue ;
518- }
519-
520- if (Z_TYPE (value ) == IS_OBJECT ) {
521- zval_ptr_dtor (& value );
522- ZVAL_NEW_STR (& value , object_str );
523- zend_string_addref (object_str );
524- }
525-
526- zend_hash_update (debug_info , string_key , & value );
527- } ZEND_HASH_FOREACH_END ();
528-
529- zend_string_release_ex (object_str , false);
530-
531- return debug_info ;
615+ return uri_get_properties (object , true);
532616}
533617
534618static HashTable * uri_get_gc_handler (zend_object * object , zval * * table , int * n )
@@ -539,6 +623,18 @@ static HashTable *uri_get_gc_handler(zend_object *object, zval **table, int *n)
539623 return zend_std_get_properties (object );
540624}
541625
626+ static HashTable * uri_get_properties_for_handler (zend_object * object , zend_prop_purpose purpose )
627+ {
628+ switch (purpose ) {
629+ case ZEND_PROP_PURPOSE_ARRAY_CAST :
630+ case ZEND_PROP_PURPOSE_VAR_EXPORT :
631+ case ZEND_PROP_PURPOSE_JSON :
632+ return uri_get_properties (object , false);
633+ default :
634+ return zend_std_get_properties_for (object , purpose );
635+ }
636+ }
637+
542638PHPAPI void php_uri_implementation_set_object_handlers (zend_class_entry * ce , zend_object_handlers * object_handlers )
543639{
544640 ce -> create_object = uri_create_object_handler ;
@@ -554,6 +650,7 @@ PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zen
554650 object_handlers -> clone_obj = uri_clone_obj_handler ;
555651 object_handlers -> get_debug_info = uri_get_debug_info_handler ;
556652 object_handlers -> get_gc = uri_get_gc_handler ;
653+ object_handlers -> get_properties_for = uri_get_properties_for_handler ;
557654}
558655
559656void uri_register_symbols (void )
0 commit comments