Skip to content

Commit 9e07dfb

Browse files
committed
handle deprecations
1 parent 61c4ea6 commit 9e07dfb

8 files changed

Lines changed: 419 additions & 15 deletions

File tree

docs/docs.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,19 @@
7272
"dark": "/logo/dark.svg"
7373
},
7474
"navbar": {
75-
"links": [
76-
{
77-
"label": "Support",
78-
"href": "mailto:hi@cortexphp.com"
79-
}
80-
],
8175
"primary": {
82-
"type": "button",
83-
"label": "Dashboard",
84-
"href": "https://dashboard.mintlify.com"
76+
"type": "github",
77+
"href": "https://github.com/cortexphp"
8578
}
8679
},
80+
"contextual": {
81+
"options": [
82+
"copy",
83+
"view",
84+
"chatgpt",
85+
"claude"
86+
]
87+
},
8788
"footer": {
8889
"socials": {
8990
"github": "https://github.com/cortexphp"

src/Contracts/JsonSchema.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public function nullable(): static;
4343
*/
4444
public function default(mixed $value): static;
4545

46+
/**
47+
* Mark the schema as deprecated.
48+
*/
49+
public function deprecated(bool $deprecated = true): static;
50+
4651
/**
4752
* Set the allowed enum values.
4853
*

src/Converters/ClassConverter.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,14 @@ public function convert(): ObjectSchema
4141
{
4242
$objectSchema = new ObjectSchema(schemaVersion: $this->version);
4343

44+
$docParser = $this->getDocParser($this->reflection);
45+
46+
if ($docParser?->isDeprecated() === true) {
47+
$objectSchema->deprecated();
48+
}
49+
4450
// Get the description from the doc parser
45-
$description = $this->getDocParser($this->reflection)?->description() ?? null;
51+
$description = $docParser?->description() ?? null;
4652

4753
// Add the description to the schema if it exists
4854
if ($description !== null) {
@@ -74,7 +80,13 @@ protected function getSchemaFromReflectionProperty(
7480

7581
$jsonSchema->title($reflectionProperty->getName());
7682

77-
$variable = $this->getDocParser($reflectionProperty)?->variable();
83+
$docParser = $this->getDocParser($reflectionProperty);
84+
85+
if ($docParser?->isDeprecated() === true) {
86+
$jsonSchema->deprecated();
87+
}
88+
89+
$variable = $docParser?->variable();
7890

7991
// Add the description to the schema if it exists
8092
if ($variable?->description !== null) {

src/Converters/ClosureConverter.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,22 @@ public function convert(): ObjectSchema
3636
{
3737
$objectSchema = new ObjectSchema(schemaVersion: $this->version);
3838

39+
$docParser = $this->getDocParser();
40+
41+
if ($docParser?->isDeprecated() === true || $this->reflection->isDeprecated()) {
42+
$objectSchema->deprecated();
43+
}
44+
3945
// Get the description from the doc parser
40-
$description = $this->getDocParser()?->description() ?? null;
46+
$description = $docParser?->description() ?? null;
4147

4248
// Add the description to the schema if it exists
4349
if ($description !== null) {
4450
$objectSchema->description($description);
4551
}
4652

4753
// Get the parameters from the doc parser
48-
$params = $this->getDocParser()?->params();
54+
$params = $docParser?->params();
4955

5056
// Add the parameters to the objectschema
5157
foreach ($this->reflection->getParameters() as $parameter) {
@@ -115,9 +121,9 @@ protected function getSchemaFromReflectionParameter(
115121
return $jsonSchema;
116122
}
117123

118-
protected function getDocParser(): ?DocParser
124+
protected function getDocParser(?string $docComment = null): ?DocParser
119125
{
120-
$docComment = $this->reflection->getDocComment();
126+
$docComment ??= $this->reflection->getDocComment();
121127

122128
return is_string($docComment)
123129
? new DocParser($docComment)

src/Support/DocParser.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ public function variable(): ?NodeData
7777
return $vars[0] ?? null;
7878
}
7979

80+
/**
81+
* Determine if the docblock is marked as deprecated.
82+
*/
83+
public function isDeprecated(): bool
84+
{
85+
return $this->parse()->getTagsByName('@deprecated') !== [];
86+
}
87+
8088
/**
8189
* Map the value node to its types.
8290
*

tests/Unit/Converters/ClassConverterTest.php

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,202 @@ enum UserStatus: string
158158
],
159159
]);
160160
});
161+
162+
it('can create a schema from a deprecated class', function (): void {
163+
/**
164+
* A deprecated user model class
165+
*
166+
* @deprecated Use UserV2 instead since v2.0
167+
*/
168+
$class = new class () {
169+
/**
170+
* @var string The user's name
171+
*/
172+
public string $name;
173+
174+
/**
175+
* @var int The user's age
176+
*/
177+
public int $age;
178+
179+
/**
180+
* @var ?string The user's email address
181+
*/
182+
public ?string $email = null;
183+
};
184+
185+
$objectSchema = (new ClassConverter($class))->convert();
186+
187+
expect($objectSchema)->toBeInstanceOf(ObjectSchema::class);
188+
expect($objectSchema->toArray())->toBe([
189+
'type' => 'object',
190+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
191+
'description' => 'A deprecated user model class',
192+
'deprecated' => true,
193+
'properties' => [
194+
'name' => [
195+
'type' => 'string',
196+
'description' => "The user's name",
197+
],
198+
'age' => [
199+
'type' => 'integer',
200+
'description' => "The user's age",
201+
],
202+
'email' => [
203+
'type' => [
204+
'string',
205+
'null',
206+
],
207+
'description' => "The user's email address",
208+
'default' => null,
209+
],
210+
],
211+
'required' => [
212+
'name',
213+
'age',
214+
],
215+
]);
216+
});
217+
218+
it('can create a schema from a class with deprecated properties', function (): void {
219+
$class = new class () {
220+
/**
221+
* @var string The user's name
222+
*/
223+
public string $name;
224+
225+
/**
226+
* @var int The user's age
227+
*
228+
* @deprecated Use birthDate instead
229+
*/
230+
public int $age;
231+
232+
/**
233+
* @var ?string The user's email address
234+
*
235+
* @deprecated Email is no longer supported
236+
*/
237+
public ?string $email = null;
238+
239+
/**
240+
* @var string The user's birth date
241+
*/
242+
public string $birthDate;
243+
};
244+
245+
$objectSchema = (new ClassConverter($class))->convert();
246+
247+
expect($objectSchema)->toBeInstanceOf(ObjectSchema::class);
248+
expect($objectSchema->toArray())->toBe([
249+
'type' => 'object',
250+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
251+
'properties' => [
252+
'name' => [
253+
'type' => 'string',
254+
'description' => "The user's name",
255+
],
256+
'age' => [
257+
'type' => 'integer',
258+
'description' => "The user's age",
259+
'deprecated' => true,
260+
],
261+
'email' => [
262+
'type' => [
263+
'string',
264+
'null',
265+
],
266+
'description' => "The user's email address",
267+
'default' => null,
268+
'deprecated' => true,
269+
],
270+
'birthDate' => [
271+
'type' => 'string',
272+
'description' => "The user's birth date",
273+
],
274+
],
275+
'required' => [
276+
'name',
277+
'age',
278+
'birthDate',
279+
],
280+
]);
281+
});
282+
283+
it('can create a schema from a deprecated class with deprecated properties', function (): void {
284+
/**
285+
* Legacy user model
286+
*
287+
* @deprecated This entire class is deprecated, use UserV3 instead
288+
*/
289+
$class = new class () {
290+
/**
291+
* @var string The user's name
292+
*/
293+
public string $name;
294+
295+
/**
296+
* @var int The user's age
297+
*
298+
* @deprecated Age property is deprecated within this deprecated class
299+
*/
300+
public int $age;
301+
};
302+
303+
$objectSchema = (new ClassConverter($class))->convert();
304+
305+
expect($objectSchema)->toBeInstanceOf(ObjectSchema::class);
306+
expect($objectSchema->toArray())->toBe([
307+
'type' => 'object',
308+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
309+
'description' => 'Legacy user model',
310+
'deprecated' => true,
311+
'properties' => [
312+
'name' => [
313+
'type' => 'string',
314+
'description' => "The user's name",
315+
],
316+
'age' => [
317+
'type' => 'integer',
318+
'description' => "The user's age",
319+
'deprecated' => true,
320+
],
321+
],
322+
'required' => [
323+
'name',
324+
'age',
325+
],
326+
]);
327+
});
328+
329+
it('can create a schema from a deprecated class without description', function (): void {
330+
/**
331+
* @deprecated
332+
*/
333+
$class = new class () {
334+
public string $name;
335+
336+
public int $age;
337+
};
338+
339+
$objectSchema = (new ClassConverter($class))->convert();
340+
341+
expect($objectSchema)->toBeInstanceOf(ObjectSchema::class);
342+
expect($objectSchema->toArray())->toBe([
343+
'type' => 'object',
344+
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
345+
'deprecated' => true,
346+
'properties' => [
347+
'name' => [
348+
'type' => 'string',
349+
],
350+
'age' => [
351+
'type' => 'integer',
352+
],
353+
],
354+
'required' => [
355+
'name',
356+
'age',
357+
],
358+
]);
359+
});

0 commit comments

Comments
 (0)