From 842bd71a18ff99d3fe2d93964d63d7f3e7f54c24 Mon Sep 17 00:00:00 2001 From: lexx Date: Thu, 14 Mar 2024 22:12:26 +0200 Subject: [PATCH] Json Schema transformer is done Form builder stuck on infinite recurrsion --- composer.json | 3 +- composer.lock | 196 +++++++++++++++++- src/Config/main.php | 1 + src/JsonSchema/Command/GenerateJsonSchema.php | 75 +++++++ src/JsonSchema/Definition.php | 103 +++++++++ src/JsonSchema/JsonSchemaService.php | 13 ++ src/JsonSchema/Property/Property.php | 7 + src/JsonSchema/Property/PropertyType.php | 8 + src/JsonSchema/Property/RefProperty.php | 32 +++ src/JsonSchema/Property/RefType.php | 9 + src/JsonSchema/Property/TypeProperty.php | 37 ++++ src/JsonSchema/SchemaData.php | 24 +++ src/LucentServiceProvider.php | 2 + src/Schema/BlockUi/File.php | 17 ++ src/Schema/FieldInterface.php | 2 + src/Schema/Ui/Block.php | 26 +++ src/Schema/Ui/Checkbox.php | 26 +++ src/Schema/Ui/Color.php | 26 +++ src/Schema/Ui/Date.php | 26 +++ src/Schema/Ui/Datetime.php | 27 +++ src/Schema/Ui/File.php | 24 +++ src/Schema/Ui/Json.php | 26 +++ src/Schema/Ui/Markdown.php | 26 +++ src/Schema/Ui/Number.php | 28 +++ src/Schema/Ui/Reference.php | 26 ++- src/Schema/Ui/Rich.php | 28 +++ src/Schema/Ui/Slug.php | 26 +++ src/Schema/Ui/Text.php | 26 +++ src/Schema/Ui/Textarea.php | 26 +++ src/Schema/Ui/Uuid.php | 26 +++ 30 files changed, 919 insertions(+), 3 deletions(-) create mode 100644 src/JsonSchema/Command/GenerateJsonSchema.php create mode 100644 src/JsonSchema/Definition.php create mode 100644 src/JsonSchema/JsonSchemaService.php create mode 100644 src/JsonSchema/Property/Property.php create mode 100644 src/JsonSchema/Property/PropertyType.php create mode 100644 src/JsonSchema/Property/RefProperty.php create mode 100644 src/JsonSchema/Property/RefType.php create mode 100644 src/JsonSchema/Property/TypeProperty.php create mode 100644 src/JsonSchema/SchemaData.php diff --git a/composer.json b/composer.json index ea0bcf7..55bbb02 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "phpoption/phpoption": "^1.9", "spatie/image-optimizer": "^1.6", "staudenmeir/laravel-cte": "^1.0", - "ext-pdo": "*" + "ext-pdo": "*", + "opis/json-schema": "^2.3" }, "require-dev": { "phpstan/phpstan": "^1.8" diff --git a/composer.lock b/composer.lock index c516096..5bdb85f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "351290446963296c5fabf750b3077a95", + "content-hash": "63bda0f783c53f088a85b8b35874ff00", "packages": [ { "name": "brick/math", @@ -1053,6 +1053,196 @@ ], "time": "2023-09-25T11:31:05+00:00" }, + { + "name": "opis/json-schema", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/opis/json-schema.git", + "reference": "c48df6d7089a45f01e1c82432348f2d5976f9bfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/json-schema/zipball/c48df6d7089a45f01e1c82432348f2d5976f9bfb", + "reference": "c48df6d7089a45f01e1c82432348f2d5976f9bfb", + "shasum": "" + }, + "require": { + "ext-json": "*", + "opis/string": "^2.0", + "opis/uri": "^1.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ext-bcmath": "*", + "ext-intl": "*", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\JsonSchema\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + }, + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + } + ], + "description": "Json Schema Validator for PHP", + "homepage": "https://opis.io/json-schema", + "keywords": [ + "json", + "json-schema", + "schema", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/opis/json-schema/issues", + "source": "https://github.com/opis/json-schema/tree/2.3.0" + }, + "time": "2022-01-08T20:38:03+00:00" + }, + { + "name": "opis/string", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/opis/string.git", + "reference": "9ebf1a1f873f502f6859d11210b25a4bf5d141e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/string/zipball/9ebf1a1f873f502f6859d11210b25a4bf5d141e7", + "reference": "9ebf1a1f873f502f6859d11210b25a4bf5d141e7", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\String\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Multibyte strings as objects", + "homepage": "https://opis.io/string", + "keywords": [ + "multi-byte", + "opis", + "string", + "string manipulation", + "utf-8" + ], + "support": { + "issues": "https://github.com/opis/string/issues", + "source": "https://github.com/opis/string/tree/2.0.1" + }, + "time": "2022-01-14T15:42:23+00:00" + }, + { + "name": "opis/uri", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opis/uri.git", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/uri/zipball/0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "shasum": "" + }, + "require": { + "opis/string": "^2.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Build, parse and validate URIs and URI-templates", + "homepage": "https://opis.io", + "keywords": [ + "URI Template", + "parse url", + "punycode", + "uri", + "uri components", + "url", + "validate uri" + ], + "support": { + "issues": "https://github.com/opis/uri/issues", + "source": "https://github.com/opis/uri/tree/1.1.0" + }, + "time": "2021-05-22T15:57:08+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.1", @@ -2261,6 +2451,10 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { + "ext-xml": "*", + "ext-zip": "*", + "ext-sqlite3": "*", + "ext-imagick": "*", "php": "^8.2", "ext-pdo": "*" }, diff --git a/src/Config/main.php b/src/Config/main.php index 5e91321..e490255 100644 --- a/src/Config/main.php +++ b/src/Config/main.php @@ -3,6 +3,7 @@ return [ "env" => env("LUCENT_ENV", "production"), "schemas_path" => env("LUCENT_SCHEMAS_PATH", "app/Lucent"), + "json_schemas_path" => env("LUCENT_JSON_SCHEMA_PATH", "json_schemas"), "database" => env('LUCENT_DB_CONNECTION', env('DB_CONNECTION',"sqlite")), "name" => env("LUCENT_NAME", "Lucent"), "url" => env("LUCENT_URL", env('APP_URL')), diff --git a/src/JsonSchema/Command/GenerateJsonSchema.php b/src/JsonSchema/Command/GenerateJsonSchema.php new file mode 100644 index 0000000..fb90f0d --- /dev/null +++ b/src/JsonSchema/Command/GenerateJsonSchema.php @@ -0,0 +1,75 @@ +channelService->channel->schemas->whereIn("type", [Type::COLLECTION, Type::FILES])->values()->map(fn(Schema $schema) => $this->fromSchema($schema)); + $definitions->map(function (Definition $definition) use ($definitions) { + $this->writeToFile($definition,$definitions); + }); + } + + private function fromSchema(Schema $schema): Definition + { + $properties = $schema->fields->map(fn(FieldInterface $field) => $field->toJsonSchema()); + + return $this->jsonSchemaService->create(new SchemaData( + id: $schema->name, + title: $schema->label, + properties: $properties, + required: $schema->fields->filter(fn(FieldInterface $field) => $field->isRequired())->values()->pluck("name"), + )); + + } + + private function writeToFile(Definition $definition, Collection $definitions): void + { + $json_schema_dir = public_path(config('lucent.json_schemas_path')); + if (!file_exists($json_schema_dir)) { + mkdir($json_schema_dir); + } + $nameAr = explode("/", $definition->_id); + $name = end($nameAr); + + $defArray = $definition->toArray(); + $defArray['$defs'] = $definitions->map(fn($def) => $def->toArray())->keyBy(function ($def){ + $nameAr = explode("/", $def['$id']); + return str_replace(".json","",end($nameAr)); + }); + + unset($defArray['$defs'][str_replace(".json","",$name)]); + + file_put_contents($json_schema_dir . "/" . $name,json_encode($defArray,JSON_UNESCAPED_SLASHES)); + } + + +} \ No newline at end of file diff --git a/src/JsonSchema/Definition.php b/src/JsonSchema/Definition.php new file mode 100644 index 0000000..5807615 --- /dev/null +++ b/src/JsonSchema/Definition.php @@ -0,0 +1,103 @@ + $properties + * @param Collection $required + */ + private function __construct( + public string $_schema, + public string $_id, + public string $title, + public string $type, + public Collection $properties, + public Collection $required, + ) + { + } + + public static function new(SchemaData $schemaData) + { + return new self( + _schema: "https://json-schema.org/draft/2020-12/schema", + _id: self::getBasePath($schemaData->id), + title: $schemaData->title, + type: "object", + properties: $schemaData->properties, + required: $schemaData->required, + ); + } + + + private static function getBasePath(string $schemaName): string + { + return config("lucent.url") . "/" . config("lucent.json_schemas_path") . "/" . $schemaName . ".json"; + } + + private static function getRefPath(string $schemaName): string + { + return '#/$defs/' . $schemaName ; + } + + + public function toArray(): array + { + $newProperties = [ + "random" => [ + "type" => "string", + "title" => "Random" + ] + ]; + foreach ($this->properties->toArray() as $property) { + $newProperty = []; + foreach ($property as $key => $value) { + if (($value instanceof Option && $value->isEmpty()) || in_array($key, ["id", "_ref"])) { + continue; + } + if ($value instanceof Option) { + $newProperty[$key] = $value->get(); + continue; + } + $newProperty[$key] = $value; + + } + + if ($property instanceof RefProperty) { + $newProperty[$property->type->value] = $property->_ref->map(function (string $ref) { + return [ + '$ref' => self::getRefPath($ref) + ]; + }); + + unset($newProperty["type"]); + } + + $newProperties[$property->id] = $newProperty; + } + + + $output = ['$schema' => $this->_schema, '$id' => $this->_id, ...toArray($this)]; + + $output["properties"] = $newProperties; + unset($output["_schema"]); + unset($output["_id"]); + unset($output["_defs"]); + return $output; + } + +} \ No newline at end of file diff --git a/src/JsonSchema/JsonSchemaService.php b/src/JsonSchema/JsonSchemaService.php new file mode 100644 index 0000000..bf6f377 --- /dev/null +++ b/src/JsonSchema/JsonSchemaService.php @@ -0,0 +1,13 @@ + $title + * @param Option $description + * @param Collection $_ref + * @param Option $minItems + * @param Option $maxItems + * @param Option $comment + */ + public function __construct( + public RefType $type, + public string $id, + public Option $title, + public Option $description, + public Collection $_ref, + public Option $minItems, + public Option $maxItems, + public Option $comment, + ) + { + } +} \ No newline at end of file diff --git a/src/JsonSchema/Property/RefType.php b/src/JsonSchema/Property/RefType.php new file mode 100644 index 0000000..757c870 --- /dev/null +++ b/src/JsonSchema/Property/RefType.php @@ -0,0 +1,9 @@ + $title + * @param Option $description + * @param Option $default + * @param Option $minLength + * @param Option $maxLength + * @param Option $readOnly + * @param Option $enum + * @param Option $comment + * @param Option $format + */ + public function __construct( + public PropertyType $type, + public string $id, + public Option $title, + public Option $description, + public Option $default, + public Option $minLength, + public Option $maxLength, + public Option $readOnly, + public Option $enum, + public Option $comment, + public Option $format, + ) + { + } +} \ No newline at end of file diff --git a/src/JsonSchema/SchemaData.php b/src/JsonSchema/SchemaData.php new file mode 100644 index 0000000..f663648 --- /dev/null +++ b/src/JsonSchema/SchemaData.php @@ -0,0 +1,24 @@ + $properties + * @param Collection $required + */ + public function __construct( + public string $id, + public string $title, + public Collection $properties, + public Collection $required, + ) + { + } +} \ No newline at end of file diff --git a/src/LucentServiceProvider.php b/src/LucentServiceProvider.php index d8c8221..493782b 100644 --- a/src/LucentServiceProvider.php +++ b/src/LucentServiceProvider.php @@ -13,6 +13,7 @@ use Lucent\Commands\RebuildThumbnails; use Lucent\Commands\RemoveOrphanEdges; use Lucent\File\FileService; use Lucent\File\ImageService; +use Lucent\JsonSchema\Command\GenerateJsonSchema; use Lucent\Query\DatabaseGraph\DatabaseGraph; use Lucent\Query\DatabaseGraph\PgsqlDatabaseGraph; use Lucent\Query\DatabaseGraph\SqliteDatabaseGraph; @@ -70,6 +71,7 @@ class LucentServiceProvider extends ServiceProvider RebuildThumbnails::class, LiveLink::class, RemoveOrphanEdges::class, + GenerateJsonSchema::class, ]); } diff --git a/src/Schema/BlockUi/File.php b/src/Schema/BlockUi/File.php index cee53fd..8b09955 100644 --- a/src/Schema/BlockUi/File.php +++ b/src/Schema/BlockUi/File.php @@ -50,5 +50,22 @@ class File implements FieldInterface, MinMaxInterface return count($value) < $this->min; } + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: Option::fromValue($this->selectOptions), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } + } diff --git a/src/Schema/FieldInterface.php b/src/Schema/FieldInterface.php index d7877a1..2e871df 100644 --- a/src/Schema/FieldInterface.php +++ b/src/Schema/FieldInterface.php @@ -7,5 +7,7 @@ interface FieldInterface { public function format(array $input, array $output): array; + public function isRequired(): bool; + } diff --git a/src/Schema/Ui/Block.php b/src/Schema/Ui/Block.php index 1e0a86c..9ba650c 100644 --- a/src/Schema/Ui/Block.php +++ b/src/Schema/Ui/Block.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Block implements FieldInterface, RequiredInterface { @@ -43,4 +47,26 @@ class Block implements FieldInterface, RequiredInterface { return empty($value); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: none(), + maxLength: none(), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Checkbox.php b/src/Schema/Ui/Checkbox.php index 6554556..5dd62d3 100644 --- a/src/Schema/Ui/Checkbox.php +++ b/src/Schema/Ui/Checkbox.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; use function is_bool; class Checkbox implements FieldInterface, RequiredInterface @@ -45,5 +49,27 @@ class Checkbox implements FieldInterface, RequiredInterface { return (bool)$value !== true; } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: none(), + maxLength: none(), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Color.php b/src/Schema/Ui/Color.php index 7d9eb43..e9d4da1 100644 --- a/src/Schema/Ui/Color.php +++ b/src/Schema/Ui/Color.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Color implements FieldInterface, RequiredInterface { @@ -41,5 +45,27 @@ class Color implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: none(), + maxLength: none(), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Date.php b/src/Schema/Ui/Date.php index 89c43e3..567f40d 100644 --- a/src/Schema/Ui/Date.php +++ b/src/Schema/Ui/Date.php @@ -3,12 +3,16 @@ namespace Lucent\Schema\Ui; use Carbon\Carbon; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\MinMaxInterface; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Date implements FieldInterface, RequiredInterface, MinMaxInterface { @@ -70,5 +74,27 @@ class Date implements FieldInterface, RequiredInterface, MinMaxInterface return $value->greaterThan($this->max); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: some("date"), + ); + } } diff --git a/src/Schema/Ui/Datetime.php b/src/Schema/Ui/Datetime.php index 92ded49..0c8bb6e 100644 --- a/src/Schema/Ui/Datetime.php +++ b/src/Schema/Ui/Datetime.php @@ -3,12 +3,16 @@ namespace Lucent\Schema\Ui; use Carbon\Carbon; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\MinMaxInterface; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Datetime implements FieldInterface, RequiredInterface, MinMaxInterface { @@ -70,5 +74,28 @@ class Datetime implements FieldInterface, RequiredInterface, MinMaxInterface return $value->greaterThan($this->max); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: some("date-time"), + ); + } + } diff --git a/src/Schema/Ui/File.php b/src/Schema/Ui/File.php index 68514a0..8749415 100644 --- a/src/Schema/Ui/File.php +++ b/src/Schema/Ui/File.php @@ -2,10 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\RefProperty; +use Lucent\JsonSchema\Property\RefType; +use Lucent\Primitive\Collection; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Validator\MinMaxInterface; +use PhpOption\Option; class File implements FieldInterface, MinMaxInterface { @@ -52,5 +57,24 @@ class File implements FieldInterface, MinMaxInterface return count($value) < $this->min; } + public function toJsonSchema(): Property + { + return new RefProperty( + type: RefType::ANY_OF, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + _ref: new Collection($this->collections), + minItems: Option::fromValue($this->min), + maxItems: Option::fromValue($this->max), + comment: Option::fromValue($this->group, ""), + ); + } + + public function isRequired(): bool + { + return $this->min > 0; + } + } diff --git a/src/Schema/Ui/Json.php b/src/Schema/Ui/Json.php index 04d1db0..d3bf65d 100644 --- a/src/Schema/Ui/Json.php +++ b/src/Schema/Ui/Json.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Json implements FieldInterface, RequiredInterface { @@ -43,4 +47,26 @@ class Json implements FieldInterface, RequiredInterface { return empty($value); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: none(), + maxLength: none(), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Markdown.php b/src/Schema/Ui/Markdown.php index 036215a..78252b8 100644 --- a/src/Schema/Ui/Markdown.php +++ b/src/Schema/Ui/Markdown.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Markdown implements FieldInterface, RequiredInterface { @@ -39,4 +43,26 @@ class Markdown implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Number.php b/src/Schema/Ui/Number.php index 90cfbd7..9413f94 100644 --- a/src/Schema/Ui/Number.php +++ b/src/Schema/Ui/Number.php @@ -2,12 +2,16 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\MinMaxInterface; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Number implements FieldInterface, RequiredInterface, MinMaxInterface { @@ -74,5 +78,29 @@ class Number implements FieldInterface, RequiredInterface, MinMaxInterface return $value > $this->min; } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } + + } diff --git a/src/Schema/Ui/Reference.php b/src/Schema/Ui/Reference.php index a1098e8..594bcfb 100644 --- a/src/Schema/Ui/Reference.php +++ b/src/Schema/Ui/Reference.php @@ -2,10 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\RefProperty; +use Lucent\JsonSchema\Property\RefType; +use Lucent\Primitive\Collection; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Validator\MinMaxInterface; +use PhpOption\Option; class Reference implements FieldInterface, MinMaxInterface { @@ -22,7 +27,7 @@ class Reference implements FieldInterface, MinMaxInterface public ?int $min = null, public ?int $max = null, public array $collections = [], - public string $searchField = "", + public string $searchField = "", public string $layout = "", public string $group = "", ) @@ -53,5 +58,24 @@ class Reference implements FieldInterface, MinMaxInterface return count($value) < $this->min; } + public function isRequired(): bool + { + return $this->min > 0; + } + + public function toJsonSchema(): Property + { + return new RefProperty( + type: RefType::ANY_OF, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + _ref: new Collection($this->collections), + minItems: Option::fromValue($this->min), + maxItems: Option::fromValue($this->max), + comment: Option::fromValue($this->group, ""), + ); + } + } diff --git a/src/Schema/Ui/Rich.php b/src/Schema/Ui/Rich.php index 82a6c6d..519a909 100644 --- a/src/Schema/Ui/Rich.php +++ b/src/Schema/Ui/Rich.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Rich implements FieldInterface, RequiredInterface { @@ -39,4 +43,28 @@ class Rich implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum:none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } + + } diff --git a/src/Schema/Ui/Slug.php b/src/Schema/Ui/Slug.php index fbf8bd1..d69d07c 100644 --- a/src/Schema/Ui/Slug.php +++ b/src/Schema/Ui/Slug.php @@ -3,11 +3,15 @@ namespace Lucent\Schema\Ui; use Illuminate\Support\Str; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Slug implements FieldInterface, RequiredInterface { @@ -46,5 +50,27 @@ class Slug implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } } diff --git a/src/Schema/Ui/Text.php b/src/Schema/Ui/Text.php index 0fe88ec..664c7ad 100644 --- a/src/Schema/Ui/Text.php +++ b/src/Schema/Ui/Text.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Text implements FieldInterface, RequiredInterface { @@ -44,5 +48,27 @@ class Text implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: Option::fromValue(array_keys($this->selectOptions ?? []),[]), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } + + public function isRequired(): bool + { + return $this->required; + } } diff --git a/src/Schema/Ui/Textarea.php b/src/Schema/Ui/Textarea.php index d575ba3..876f1cc 100644 --- a/src/Schema/Ui/Textarea.php +++ b/src/Schema/Ui/Textarea.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Textarea implements FieldInterface, RequiredInterface { @@ -41,5 +45,27 @@ class Textarea implements FieldInterface, RequiredInterface return empty(trim($value)); } + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: Option::fromValue($this->default, ""), + minLength: Option::fromValue($this->min), + maxLength: Option::fromValue($this->max), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: none(), + ); + } + } diff --git a/src/Schema/Ui/Uuid.php b/src/Schema/Ui/Uuid.php index 3d422ff..ebefd77 100644 --- a/src/Schema/Ui/Uuid.php +++ b/src/Schema/Ui/Uuid.php @@ -2,11 +2,15 @@ namespace Lucent\Schema\Ui; +use Lucent\JsonSchema\Property\Property; +use Lucent\JsonSchema\Property\PropertyType; +use Lucent\JsonSchema\Property\TypeProperty; use Lucent\Schema\FieldInfo; use Lucent\Schema\FieldInterface; use Lucent\Schema\FieldType; use Lucent\Schema\Nullable; use Lucent\Schema\Validator\RequiredInterface; +use PhpOption\Option; class Uuid implements FieldInterface, RequiredInterface { @@ -37,5 +41,27 @@ class Uuid implements FieldInterface, RequiredInterface { return empty(trim($value)); } + + public function isRequired(): bool + { + return $this->required; + } + + public function toJsonSchema(): Property + { + return new TypeProperty( + type: PropertyType::STRING, + id: $this->name, + title: Option::fromValue($this->label), + description: Option::fromValue($this->help, ""), + default: none(), + minLength: none(), + maxLength: none(), + readOnly: Option::fromValue($this->readonly, false), + enum: none(), + comment: Option::fromValue($this->group, ""), + format: some("uuid"), + ); + } }