@@ -257,6 +257,7 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
257
257
break ;
258
258
case REF_TYPE_ATTRIBUTE :
259
259
attr_reference = (attribute_reference * )intern -> ptr ;
260
+ zend_string_release (attr_reference -> name );
260
261
zval_ptr_dtor (& attr_reference -> arguments );
261
262
efree (attr_reference );
262
263
break ;
@@ -1047,38 +1048,112 @@ static void reflection_attribute_factory(zval *object, zend_string *name, zval *
1047
1048
reflection_instantiate (reflection_attribute_ptr , object );
1048
1049
intern = Z_REFLECTION_P (object );
1049
1050
reference = (attribute_reference * ) emalloc (sizeof (attribute_reference ));
1050
- reference -> name = name ;
1051
+ reference -> name = zend_string_copy ( name ) ;
1051
1052
ZVAL_COPY (& reference -> arguments , arguments );
1052
1053
intern -> ptr = reference ;
1053
1054
intern -> ref_type = REF_TYPE_ATTRIBUTE ;
1054
1055
}
1055
1056
/* }}} */
1056
1057
1058
+ static int convert_ast_to_zval (zval * ret , zend_ast * ast , zend_class_entry * ce )
1059
+ {
1060
+ if (ast -> kind == ZEND_AST_CONSTANT ) {
1061
+ zend_string * name = zend_ast_get_constant_name (ast );
1062
+ zval * zv = zend_get_constant_ex (name , ce , ast -> attr );
1063
+
1064
+ if (UNEXPECTED (zv == NULL )) {
1065
+ return FAILURE ;
1066
+ }
1067
+
1068
+ ZVAL_COPY_OR_DUP (ret , zv );
1069
+ } else {
1070
+ zval tmp ;
1071
+
1072
+ if (UNEXPECTED (zend_ast_evaluate (& tmp , ast , ce ) != SUCCESS )) {
1073
+ return FAILURE ;
1074
+ }
1075
+
1076
+ ZVAL_COPY_OR_DUP (ret , & tmp );
1077
+ zval_ptr_dtor (& tmp );
1078
+ }
1079
+
1080
+ return SUCCESS ;
1081
+ }
1082
+
1083
+ static int convert_ast_attributes (zval * ret , HashTable * attributes , zend_class_entry * ce )
1084
+ {
1085
+ Bucket * p ;
1086
+ zval tmp ;
1087
+
1088
+ array_init (ret );
1089
+
1090
+ ZEND_HASH_FOREACH_BUCKET (attributes , p ) {
1091
+ if (!p -> key && p -> h == 0 ) {
1092
+ continue ;
1093
+ }
1094
+
1095
+ if (Z_TYPE (p -> val ) == IS_CONSTANT_AST ) {
1096
+ if (FAILURE == convert_ast_to_zval (& tmp , Z_ASTVAL (p -> val ), ce )) {
1097
+ return FAILURE ;
1098
+ }
1099
+
1100
+ add_next_index_zval (ret , & tmp );
1101
+ } else {
1102
+ Z_TRY_ADDREF (p -> val );
1103
+ add_next_index_zval (ret , & p -> val );
1104
+ }
1105
+ } ZEND_HASH_FOREACH_END ();
1106
+
1107
+ return SUCCESS ;
1108
+ }
1057
1109
1058
1110
static int convert_attributes (zval * ret , HashTable * attributes , zend_class_entry * ce )
1059
1111
{
1060
- zend_string * attribute_name ;
1061
- zval * attr ;
1112
+ Bucket * p ;
1113
+ zval * v ;
1062
1114
1063
- zval converted_attributes ;
1115
+ zval result ;
1064
1116
zval obj ;
1065
1117
1066
1118
array_init (ret );
1067
1119
1068
- ZEND_HASH_FOREACH_STR_KEY_VAL (attributes , attribute_name , attr ) {
1069
- if (!attribute_name ) {
1120
+ ZEND_HASH_FOREACH_BUCKET (attributes , p ) {
1121
+ if (!p -> key ) {
1122
+ // Skip inlined parameter annotations.
1070
1123
continue ;
1071
1124
}
1072
1125
1073
- if (FAILURE == zend_ast_convert_attributes (& converted_attributes , Z_ARRVAL_P (attr ), ce )) {
1074
- zval_ptr_dtor (ret );
1075
- return FAILURE ;
1076
- }
1126
+ ZEND_ASSERT (Z_TYPE (p -> val ) == IS_ARRAY );
1077
1127
1078
- reflection_attribute_factory (& obj , attribute_name , & converted_attributes );
1079
- zval_ptr_dtor (& converted_attributes );
1128
+ v = zend_hash_index_find (Z_ARRVAL (p -> val ), 0 );
1080
1129
1081
- add_next_index_zval (ret , & obj );
1130
+ if (Z_TYPE_P (v ) == IS_STRING ) {
1131
+ if (FAILURE == convert_ast_attributes (& result , Z_ARRVAL (p -> val ), ce )) {
1132
+ zval_ptr_dtor (ret );
1133
+ return FAILURE ;
1134
+ }
1135
+
1136
+ reflection_attribute_factory (& obj , Z_STR_P (v ), & result );
1137
+ add_next_index_zval (ret , & obj );
1138
+ zval_ptr_dtor (& result );
1139
+ } else {
1140
+ zval * zv ;
1141
+
1142
+ ZEND_ASSERT (Z_TYPE_P (v ) == IS_ARRAY );
1143
+
1144
+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL (p -> val ), zv ) {
1145
+ ZEND_ASSERT (Z_TYPE_P (zv ) == IS_ARRAY );
1146
+
1147
+ if (FAILURE == convert_ast_attributes (& result , Z_ARRVAL_P (zv ), ce )) {
1148
+ zval_ptr_dtor (ret );
1149
+ return FAILURE ;
1150
+ }
1151
+
1152
+ reflection_attribute_factory (& obj , Z_STR_P (zend_hash_index_find (Z_ARRVAL_P (zv ), 0 )), & result );
1153
+ add_next_index_zval (ret , & obj );
1154
+ zval_ptr_dtor (& result );
1155
+ } ZEND_HASH_FOREACH_END ();
1156
+ }
1082
1157
} ZEND_HASH_FOREACH_END ();
1083
1158
1084
1159
return SUCCESS ;
@@ -1701,7 +1776,6 @@ ZEND_METHOD(reflection_function, getAttributes)
1701
1776
if (zend_parse_parameters_none () == FAILURE ) {
1702
1777
return ;
1703
1778
}
1704
-
1705
1779
GET_REFLECTION_OBJECT_PTR (fptr );
1706
1780
1707
1781
if (fptr -> type == ZEND_USER_FUNCTION && fptr -> op_array .attributes ) {
@@ -2640,6 +2714,37 @@ ZEND_METHOD(reflection_parameter, canBePassedByValue)
2640
2714
}
2641
2715
/* }}} */
2642
2716
2717
+ /* {{{ proto public bool ReflectionParameter::getAttributes(?string $name = null)
2718
+ Get parameter attributes. */
2719
+ ZEND_METHOD (reflection_parameter , getAttributes )
2720
+ {
2721
+ reflection_object * intern ;
2722
+ parameter_reference * param ;
2723
+
2724
+ if (zend_parse_parameters_none () == FAILURE ) {
2725
+ RETURN_THROWS ();
2726
+ }
2727
+ GET_REFLECTION_OBJECT_PTR (param );
2728
+
2729
+ if (param -> fptr -> type == ZEND_USER_FUNCTION && param -> fptr -> op_array .attributes ) {
2730
+ zval * attr ;
2731
+
2732
+ if (NULL != (attr = zend_hash_index_find (param -> fptr -> op_array .attributes , param -> offset ))) {
2733
+ zval ret ;
2734
+
2735
+ ZEND_ASSERT (Z_TYPE_P (attr ) == IS_ARRAY );
2736
+
2737
+ if (FAILURE == convert_attributes (& ret , Z_ARRVAL_P (attr ), param -> fptr -> common .scope )) {
2738
+ RETURN_THROWS ();
2739
+ }
2740
+
2741
+ RETURN_ZVAL (& ret , 1 , 1 );
2742
+ }
2743
+ }
2744
+
2745
+ RETURN_EMPTY_ARRAY ();
2746
+ }
2747
+
2643
2748
/* {{{ proto public bool ReflectionParameter::getPosition()
2644
2749
Returns whether this parameter is an optional parameter */
2645
2750
ZEND_METHOD (reflection_parameter , getPosition )
@@ -5626,6 +5731,7 @@ ZEND_METHOD(reflection_property, getAttributes)
5626
5731
return ;
5627
5732
}
5628
5733
GET_REFLECTION_OBJECT_PTR (ref );
5734
+
5629
5735
if (ref -> prop -> attributes ) {
5630
5736
zval ret ;
5631
5737
@@ -6614,6 +6720,7 @@ static const zend_function_entry reflection_parameter_functions[] = {
6614
6720
ZEND_ME (reflection_parameter , isArray , arginfo_class_ReflectionParameter_isArray , 0 )
6615
6721
ZEND_ME (reflection_parameter , isCallable , arginfo_class_ReflectionParameter_isCallable , 0 )
6616
6722
ZEND_ME (reflection_parameter , allowsNull , arginfo_class_ReflectionParameter_allowsNull , 0 )
6723
+ ZEND_ME (reflection_parameter , getAttributes , arginfo_class_ReflectionParameter_getAttributes , 0 )
6617
6724
ZEND_ME (reflection_parameter , getPosition , arginfo_class_ReflectionParameter_getPosition , 0 )
6618
6725
ZEND_ME (reflection_parameter , isOptional , arginfo_class_ReflectionParameter_isOptional , 0 )
6619
6726
ZEND_ME (reflection_parameter , isDefaultValueAvailable , arginfo_class_ReflectionParameter_isDefaultValueAvailable , 0 )
0 commit comments