@@ -26,16 +26,44 @@ final class ConfigurationAttributeGenerator extends AbstractAttributeGenerator
2626 */
2727 public function generateClassAttributes (Class_ $ class ): array
2828 {
29- $ typeConfig = $ this ->config ['types ' ][$ class ->name ()] ?? null ;
30- $ vocabConfig = null ;
29+ $ typeAttributes = $ this ->config ['types ' ][$ class ->name ()][ ' attributes ' ] ?? [[]] ;
30+ $ vocabAttributes = [[]] ;
3131 if ($ class instanceof SchemaClass) {
32- $ vocabConfig = $ this ->config ['vocabularies ' ][$ class ->resource ()->getGraph ()->getUri ()] ?? null ;
32+ $ vocabAttributes = $ this ->config ['vocabularies ' ][$ class ->resource ()->getGraph ()->getUri ()][ ' attributes ' ] ?? [[]] ;
3333 }
3434
35+ $ getAttributesNames = static fn (array $ config ) => $ config === [[]]
36+ ? []
37+ : array_unique (array_map (fn (array $ v ) => array_keys ($ v )[0 ], $ config ));
38+ $ typeAttributesNames = $ getAttributesNames ($ typeAttributes );
39+ $ vocabAttributesNames = $ getAttributesNames ($ vocabAttributes );
40+
41+ $ getAttribute = static fn (string $ name , array $ args ) => new Attribute (
42+ $ name ,
43+ $ args + [
44+ // An attribute from a vocabulary cannot be appended if a same one has not
45+ // previously been generated or if the same one is not mergeable.
46+ // It allows vocabulary attributes configuration to only merge the attributes args.
47+ 'alwaysGenerate ' => !\in_array ($ name , $ vocabAttributesNames , true ) ||
48+ \in_array ($ name , $ typeAttributesNames , true ),
49+ // Custom explicitly configured attributes is not mergeable with next one
50+ // but treated as repeated if given more than once.
51+ 'mergeable ' => false ,
52+ ]
53+ );
54+
3555 $ attributes = [];
36- $ configAttributes = array_merge ($ vocabConfig ['attributes ' ] ?? [], $ typeConfig ['attributes ' ] ?? []);
37- foreach ($ configAttributes as $ attributeName => $ attributeArgs ) {
38- $ attributes [] = new Attribute ($ attributeName , ($ attributeArgs ?? []) + ['alwaysGenerate ' => !isset ($ vocabConfig ['attributes ' ][$ attributeName ]) || isset ($ typeConfig ['attributes ' ][$ attributeName ])]);
56+ foreach ($ vocabAttributes as $ configAttributes ) {
57+ foreach ($ configAttributes as $ attributeName => $ attributeArgs ) {
58+ if (!\in_array ($ attributeName , $ typeAttributesNames , true )) {
59+ $ attributes [] = $ getAttribute ($ attributeName , $ attributeArgs ?? []);
60+ }
61+ }
62+ }
63+ foreach ($ typeAttributes as $ configAttributes ) {
64+ foreach ($ configAttributes as $ attributeName => $ attributeArgs ) {
65+ $ attributes [] = $ getAttribute ($ attributeName , $ attributeArgs ?? []);
66+ }
3967 }
4068
4169 return $ attributes ;
@@ -47,11 +75,16 @@ public function generateClassAttributes(Class_ $class): array
4775 public function generatePropertyAttributes (Property $ property , string $ className ): array
4876 {
4977 $ typeConfig = $ this ->config ['types ' ][$ className ] ?? null ;
50- $ propertyConfig = $ typeConfig ['properties ' ][$ property ->name ()] ?? null ;
78+ $ propertyAttributes = $ typeConfig ['properties ' ][$ property ->name ()][ ' attributes ' ] ?? [[]] ;
5179
5280 $ attributes = [];
53- foreach ($ propertyConfig ['attributes ' ] ?? [] as $ attributeName => $ attributeArgs ) {
54- $ attributes [] = new Attribute ($ attributeName , $ attributeArgs ?? []);
81+ foreach ($ propertyAttributes as $ configAttributes ) {
82+ foreach ($ configAttributes as $ attributeName => $ attributeArgs ) {
83+ $ attributes [] = new Attribute (
84+ $ attributeName ,
85+ ($ attributeArgs ?? []) + ['mergeable ' => false ]
86+ );
87+ }
5588 }
5689
5790 return $ attributes ;
0 commit comments