@@ -96,7 +96,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
96
96
97
97
if ($ this ->classAttributeConfigurators ) {
98
98
foreach ($ classReflector ->getAttributes () as $ attribute ) {
99
- if ($ configurator = $ this ->classAttributeConfigurators [ $ attribute ->getName ()] ?? null ) {
99
+ if ($ configurator = $ this ->findConfigurator ( $ this -> classAttributeConfigurators , $ attribute ->getName ()) ) {
100
100
$ configurator ($ conditionals , $ attribute ->newInstance (), $ classReflector );
101
101
}
102
102
}
@@ -112,7 +112,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
112
112
if ($ constructorReflector ) {
113
113
foreach ($ constructorReflector ->getParameters () as $ parameterReflector ) {
114
114
foreach ($ parameterReflector ->getAttributes () as $ attribute ) {
115
- if ($ configurator = $ this ->parameterAttributeConfigurators [ $ attribute ->getName ()] ?? null ) {
115
+ if ($ configurator = $ this ->findConfigurator ( $ this -> parameterAttributeConfigurators , $ attribute ->getName ()) ) {
116
116
$ configurator ($ conditionals , $ attribute ->newInstance (), $ parameterReflector );
117
117
}
118
118
}
@@ -128,7 +128,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
128
128
129
129
if ($ this ->methodAttributeConfigurators ) {
130
130
foreach ($ methodReflector ->getAttributes () as $ attribute ) {
131
- if ($ configurator = $ this ->methodAttributeConfigurators [ $ attribute ->getName ()] ?? null ) {
131
+ if ($ configurator = $ this ->findConfigurator ( $ this -> methodAttributeConfigurators , $ attribute ->getName ()) ) {
132
132
$ configurator ($ conditionals , $ attribute ->newInstance (), $ methodReflector );
133
133
}
134
134
}
@@ -137,7 +137,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
137
137
if ($ this ->parameterAttributeConfigurators ) {
138
138
foreach ($ methodReflector ->getParameters () as $ parameterReflector ) {
139
139
foreach ($ parameterReflector ->getAttributes () as $ attribute ) {
140
- if ($ configurator = $ this ->parameterAttributeConfigurators [ $ attribute ->getName ()] ?? null ) {
140
+ if ($ configurator = $ this ->findConfigurator ( $ this -> parameterAttributeConfigurators , $ attribute ->getName ()) ) {
141
141
$ configurator ($ conditionals , $ attribute ->newInstance (), $ parameterReflector );
142
142
}
143
143
}
@@ -153,7 +153,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
153
153
}
154
154
155
155
foreach ($ propertyReflector ->getAttributes () as $ attribute ) {
156
- if ($ configurator = $ this ->propertyAttributeConfigurators [ $ attribute ->getName ()] ?? null ) {
156
+ if ($ configurator = $ this ->findConfigurator ( $ this -> propertyAttributeConfigurators , $ attribute ->getName ()) ) {
157
157
$ configurator ($ conditionals , $ attribute ->newInstance (), $ propertyReflector );
158
158
}
159
159
}
@@ -167,4 +167,20 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
167
167
168
168
return parent ::processValue ($ value , $ isRoot );
169
169
}
170
+
171
+ /**
172
+ * Find the first configurator for the given attribute name, looking up the class hierarchy.
173
+ */
174
+ private function findConfigurator (array &$ configurators , string $ attributeName ): ?callable
175
+ {
176
+ if (\array_key_exists ($ attributeName , $ configurators )) {
177
+ return $ configurators [$ attributeName ];
178
+ }
179
+
180
+ if (class_exists ($ attributeName ) && $ parent = get_parent_class ($ attributeName )) {
181
+ return $ configurators [$ attributeName ] = self ::findConfigurator ($ configurators , $ parent );
182
+ }
183
+
184
+ return $ configurators [$ attributeName ] = null ;
185
+ }
170
186
}
0 commit comments