Skip to content

Commit e978ba5

Browse files
committed
adjustments
1 parent f20a682 commit e978ba5

4 files changed

Lines changed: 54 additions & 17 deletions

File tree

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717
use Cortex\JsonSchema\Types\ObjectSchema;
1818
use Cortex\JsonSchema\Exceptions\SchemaException;
1919

20-
class FromClosure
20+
class ClosureConverter
2121
{
22-
public static function convert(Closure $closure): ObjectSchema
22+
public function __construct(
23+
protected Closure $closure,
24+
) {}
25+
26+
public function convert(): ObjectSchema
2327
{
24-
$reflection = new ReflectionFunction($closure);
28+
$reflection = new ReflectionFunction($this->closure);
2529
$schema = new ObjectSchema();
2630

2731
// TODO: handle descriptions
@@ -40,6 +44,7 @@ protected static function getSchemaFromReflectionParameter(ReflectionParameter $
4044
{
4145
$type = $parameter->getType();
4246

47+
// @phpstan-ignore argument.type
4348
$schema = self::getSchemaFromReflectionType($type);
4449

4550
$schema->title($parameter->getName());
@@ -64,6 +69,7 @@ protected static function getSchemaFromReflectionParameter(ReflectionParameter $
6469
$reflection = new ReflectionEnum($typeName);
6570

6671
if ($reflection->isBacked()) {
72+
/** @var non-empty-array<array-key, \BackedEnum> */
6773
$cases = $typeName::cases();
6874
$schema->enum(array_map(fn($case): int|string => $case->value, $cases));
6975
}
@@ -81,10 +87,12 @@ protected static function getSchemaFromReflectionType(
8187
): Schema {
8288
$schemaTypes = match (true) {
8389
$type instanceof ReflectionUnionType, $type instanceof ReflectionIntersectionType => array_map(
90+
// @phpstan-ignore argument.type
8491
fn(ReflectionNamedType $t): SchemaType => self::resolveSchemaType($t),
8592
$type->getTypes(),
8693
),
8794
// If the parameter is not typed or explicitly typed as mixed, we use all schema types
95+
// TODO: use phpstan parser to get the type also
8896
in_array($type?->getName(), ['mixed', null], true) => SchemaType::cases(),
8997
default => [self::resolveSchemaType($type)],
9098
};

src/SchemaFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Cortex\JsonSchema\Types\StringSchema;
1515
use Cortex\JsonSchema\Types\BooleanSchema;
1616
use Cortex\JsonSchema\Types\IntegerSchema;
17-
use Cortex\JsonSchema\Converters\FromClosure;
17+
use Cortex\JsonSchema\Converters\ClosureConverter;
1818

1919
class SchemaFactory
2020
{
@@ -68,6 +68,6 @@ public static function mixed(?string $title = null): UnionSchema
6868

6969
public static function fromClosure(Closure $closure): ObjectSchema
7070
{
71-
return FromClosure::convert($closure);
71+
return (new ClosureConverter($closure))->convert();
7272
}
7373
}

tests/Unit/Converters/FromClosureTest.php renamed to tests/Unit/Converters/ClosureConverterTest.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
namespace Cortex\JsonSchema\Tests\Unit\Converters;
66

77
use Cortex\JsonSchema\Types\ObjectSchema;
8-
use Cortex\JsonSchema\Converters\FromClosure;
8+
use Cortex\JsonSchema\Converters\ClosureConverter;
99

1010
it('can create a schema from a closure', function (): void {
1111
$closure = function (string $name, array $fooArray, ?int $age = null): void {};
12-
$schema = FromClosure::convert($closure);
12+
$schema = (new ClosureConverter($closure))->convert();
1313

1414
expect($schema)->toBeInstanceOf(ObjectSchema::class);
1515
expect($schema->toArray())->toBe([
@@ -44,7 +44,7 @@ enum MyEnum: string
4444
}
4545

4646
$closure = function (MyEnum $myEnum, bool $foo = true): void {};
47-
$schema = FromClosure::convert($closure);
47+
$schema = (new ClosureConverter($closure))->convert();
4848

4949
expect($schema)->toBeInstanceOf(ObjectSchema::class);
5050
expect($schema->toArray())->toBe([
@@ -78,7 +78,7 @@ enum Status: int
7878
}
7979

8080
$closure = function (Status $status): void {};
81-
$schema = FromClosure::convert($closure);
81+
$schema = (new ClosureConverter($closure))->convert();
8282

8383
expect($schema)->toBeInstanceOf(ObjectSchema::class);
8484
expect($schema->toArray())->toBe([
@@ -102,7 +102,7 @@ enum Status: int
102102

103103
it('can create a schema from a closure with a union type', function (): void {
104104
$closure = function (int|string $foo): void {};
105-
$schema = FromClosure::convert($closure);
105+
$schema = (new ClosureConverter($closure))->convert();
106106

107107
expect($schema)->toBeInstanceOf(ObjectSchema::class);
108108
expect($schema->toArray())->toBe([
@@ -124,7 +124,7 @@ enum Status: int
124124

125125
it('can create a schema from a closure with a nullable union type', function (): void {
126126
$closure = function (int|string|null $foo): void {};
127-
$schema = FromClosure::convert($closure);
127+
$schema = (new ClosureConverter($closure))->convert();
128128

129129
expect($schema)->toBeInstanceOf(ObjectSchema::class);
130130
expect($schema->toArray())->toBe([
@@ -147,7 +147,7 @@ enum Status: int
147147

148148
it('can create a schema from a closure with array type hints', function (): void {
149149
$closure = function (array $items, array $tags = ['default']): void {};
150-
$schema = FromClosure::convert($closure);
150+
$schema = (new ClosureConverter($closure))->convert();
151151

152152
expect($schema)->toBeInstanceOf(ObjectSchema::class);
153153
expect($schema->toArray())->toBe([
@@ -170,7 +170,7 @@ enum Status: int
170170

171171
it('can create a schema from a closure with mixed type', function (): void {
172172
$closure = function (mixed $data): void {};
173-
$schema = FromClosure::convert($closure);
173+
$schema = (new ClosureConverter($closure))->convert();
174174

175175
expect($schema)->toBeInstanceOf(ObjectSchema::class);
176176
expect($schema->toArray())->toBe([
@@ -197,7 +197,7 @@ enum Status: int
197197

198198
it('can create a schema from a closure with object type', function (): void {
199199
$closure = function (object $data): void {};
200-
$schema = FromClosure::convert($closure);
200+
$schema = (new ClosureConverter($closure))->convert();
201201

202202
expect($schema)->toBeInstanceOf(ObjectSchema::class);
203203
expect($schema->toArray())->toBe([
@@ -216,7 +216,7 @@ enum Status: int
216216

217217
it('can create a schema from a closure with float type', function (): void {
218218
$closure = function (float $amount = 0.0): void {};
219-
$schema = FromClosure::convert($closure);
219+
$schema = (new ClosureConverter($closure))->convert();
220220

221221
expect($schema)->toBeInstanceOf(ObjectSchema::class);
222222
expect($schema->toArray())->toBe([
@@ -240,7 +240,7 @@ enum Status: int
240240
bool $active = true,
241241
): void {};
242242

243-
$schema = FromClosure::convert($closure);
243+
$schema = (new ClosureConverter($closure))->convert();
244244

245245
expect($schema)->toBeInstanceOf(ObjectSchema::class);
246246
expect($schema->toArray())->toBe([
@@ -277,7 +277,7 @@ enum Status: int
277277

278278
it('can create a schema from a closure with array type', function (): void {
279279
$closure = function (array $items = ['default']): void {};
280-
$schema = FromClosure::convert($closure);
280+
$schema = (new ClosureConverter($closure))->convert();
281281

282282
expect($schema)->toBeInstanceOf(ObjectSchema::class);
283283
expect($schema->toArray())->toBe([

tests/Unit/SchemaFactoryTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,32 @@
5050
expect($schemaArray)->toHaveKey('readOnly', true);
5151
expect($schemaArray)->toHaveKey('writeOnly', true);
5252
});
53+
54+
it('can create a schema from a closure', function (): void {
55+
$closure = function (string $name, array $fooArray, ?int $age = null): void {};
56+
$schema = Schema::fromClosure($closure);
57+
58+
expect($schema)->toBeInstanceOf(ObjectSchema::class);
59+
expect($schema->toArray())->toBe([
60+
'type' => 'object',
61+
'$schema' => 'http://json-schema.org/draft-07/schema#',
62+
'properties' => [
63+
'name' => [
64+
'type' => 'string',
65+
],
66+
'fooArray' => [
67+
'type' => 'array',
68+
],
69+
'age' => [
70+
'type' => [
71+
'integer',
72+
'null',
73+
],
74+
],
75+
],
76+
'required' => [
77+
'name',
78+
'fooArray',
79+
],
80+
]);
81+
});

0 commit comments

Comments
 (0)