44
55namespace Spiral \JsonSchemaGenerator ;
66
7+ use Spiral \JsonSchemaGenerator \Attribute \AdditionalProperty ;
8+ use Spiral \JsonSchemaGenerator \Attribute \Definition as ClassDefinition ;
79use Spiral \JsonSchemaGenerator \Attribute \Field ;
810use Spiral \JsonSchemaGenerator \Parser \ClassParserInterface ;
911use Spiral \JsonSchemaGenerator \Parser \Parser ;
@@ -35,6 +37,35 @@ public function generate(string|\ReflectionClass $class): Schema
3537
3638 $ schema = new Schema ();
3739
40+ // Process class-level Definition attribute if present
41+ $ classDefinition = $ class ->findAttribute (ClassDefinition::class);
42+ if ($ classDefinition !== null ) {
43+ if (!empty ($ classDefinition ->title )) {
44+ $ schema ->setTitle ($ classDefinition ->title );
45+ } else {
46+ // Use class short name as default title
47+ $ schema ->setTitle ($ class ->getShortName ());
48+ }
49+
50+ if (!empty ($ classDefinition ->description )) {
51+ $ schema ->setDescription ($ classDefinition ->description );
52+ }
53+
54+ if ($ classDefinition ->id !== null ) {
55+ $ schema ->setId ($ classDefinition ->id );
56+ }
57+
58+ if ($ classDefinition ->schemaVersion !== null ) {
59+ $ schema ->setSchemaVersion ($ classDefinition ->schemaVersion );
60+ }
61+ } else {
62+ // Set title to class name by default if no definition attribute
63+ $ schema ->setTitle ($ class ->getShortName ());
64+ }
65+
66+ // Process additional properties attributes if present
67+ $ this ->processAdditionalProperties ($ class , $ schema );
68+
3869 $ dependencies = [];
3970 // Generating properties
4071 foreach ($ class ->getProperties () as $ property ) {
@@ -80,14 +111,50 @@ public function generate(string|\ReflectionClass $class): Schema
80111 return $ schema ;
81112 }
82113
114+ /**
115+ * Process AdditionalProperty attributes on a class
116+ */
117+ protected function processAdditionalProperties (ClassParserInterface $ class , Schema $ schema ): void
118+ {
119+ // Get reflection class to extract attributes with \ReflectionClass::getAttributes()
120+ try {
121+ $ reflectionClass = new \ReflectionClass ($ class ->getName ());
122+ $ additionalProperties = $ reflectionClass ->getAttributes (AdditionalProperty::class);
123+
124+ foreach ($ additionalProperties as $ additionalProperty ) {
125+ $ instance = $ additionalProperty ->newInstance ();
126+ $ schema ->addAdditionalProperty ($ instance ->name , $ instance ->value );
127+ }
128+ } catch (\ReflectionException ) {
129+ // Silently fail, we'll just not have additional properties
130+ }
131+ }
132+
83133 protected function generateDefinition (ClassParserInterface $ class , array &$ dependencies = []): ?Definition
84134 {
85135 $ properties = [];
136+
137+ // Process class-level Definition attribute if present
138+ $ title = $ class ->getShortName ();
139+ $ description = '' ;
140+
141+ $ classDefinition = $ class ->findAttribute (ClassDefinition::class);
142+ if ($ classDefinition !== null ) {
143+ if (!empty ($ classDefinition ->title )) {
144+ $ title = $ classDefinition ->title ;
145+ }
146+
147+ if (!empty ($ classDefinition ->description )) {
148+ $ description = $ classDefinition ->description ;
149+ }
150+ }
151+
86152 if ($ class ->isEnum ()) {
87153 return new Definition (
88154 type: $ class ->getName (),
89155 options: $ class ->getEnumValues (),
90- title: $ class ->getShortName (),
156+ title: $ title ,
157+ description: $ description ,
91158 );
92159 }
93160
@@ -102,7 +169,12 @@ protected function generateDefinition(ClassParserInterface $class, array &$depen
102169 $ properties [$ property ->getName ()] = $ psc ;
103170 }
104171
105- return new Definition (type: $ class ->getName (), title: $ class ->getShortName (), properties: $ properties );
172+ return new Definition (
173+ type: $ class ->getName (),
174+ title: $ title ,
175+ description: $ description ,
176+ properties: $ properties ,
177+ );
106178 }
107179
108180 protected function generateProperty (PropertyInterface $ property ): ?Property
0 commit comments