Browse Source

more work on schema generation

dev
Cerys 3 weeks ago
parent
commit
0ee81236e3
  1. 30
      src/Attributes/SchemaDocumentField.php
  2. 171
      src/SchemaBuilder/SchemaBuilder.php

30
src/Attributes/SchemaDocumentField.php

@ -12,26 +12,34 @@ class SchemaDocumentField extends Attribute
{
public string $Name;
public SchemaFieldExistence $Existence;
public string $Comment;
public array $ValidSchemas;
public int $MaxSize;
public string $MimeType;
public ?SchemaFieldExistence $Existence;
public ?string $Comment;
public ?array $ValidSchemas;
public int $MaxSize = PHP_INT_MIN;
public ?string $MimeType;
public ?SchemaDocumentField $Child;
public ?array $Children;
public function __construct(
string $Name,
SchemaFieldExistence $Existence = SchemaFieldExistence::MAY,
string $Comment = "",
array $ValidSchemas = [],
int $MaxSize = 0,
string $MimeType = "",
SchemaDocumentField $Child = null
?SchemaFieldExistence $Existence = null,
?string $Comment = null,
?array $ValidSchemas = null,
int $MaxSize = PHP_INT_MIN,
?string $MimeType = null,
?SchemaDocumentField $Child = null,
?array $Children = null,
)
{
$this->Name = $Name;
$this->Existence = $Existence;
$this->Comment = $Comment;
$this->ValidSchemas = $ValidSchemas;
$this->MaxSize = $MaxSize;
$this->MimeType = $MimeType;
$this->Child = $Child;
$this->Children = $Children;
parent::__construct(new Name("SchemaDocumentField"), [], []);
}

171
src/SchemaBuilder/SchemaBuilder.php

@ -10,8 +10,13 @@ use JetBrains\PhpStorm\NoReturn;
use PHPUnit\Util\Exception;
use ReflectionClass;
class SchemaBuilder
{
private const CLASS_NAME_REGEX = '/^(([\\\\]*)?[a-zA-Z_][a-zA-Z0-9_]*)(([\\\\]*[a-zA-Z0-9_]*)*)$/';
private const URL_REGEX = '/^https?:\/\/[^\s$.?#].[^\s]*$/i';
/**
* Goes through the Attribute classes and makes a list of all the Properties they have.
* This is so if a user adds another variable to the Attribute constructor, it won't appear in the final Schema.
@ -60,94 +65,128 @@ class SchemaBuilder
return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $input));
}
/**
* @throws SchemaDocumentFieldNameUnsetException
*/
public static function GenerateSchema(string $targetSchemaClassName): array
private static function ProcessSchemaPropertyArguments($arguments): array
{
$schema = [];
$validKeys = self::GetValidKeys();
$reflection = new ReflectionClass(new $targetSchemaClassName());
/*
* Schema "meta-data" from here...
*/
foreach($reflection->getAttributes()[0]->getArguments() as $key=>$value)
if(self::VerifyField($key, $value, $validKeys[0]))
$schema["@" . self::PascalCaseToSnakeCase(input: $key)] = $value;
/*
* Property handling from here...
*/
foreach ($reflection->getProperties() as $property)
{
$classNameRegex = '/^([\\]*)?[a-zA-Z_][a-zA-Z0-9_]*)(([\\]*[a-zA-Z0-9_]*)*)$/';
$urlRegex = '/^https?:\/\/[^\s$.?#].[^\s]*$/i';
$propertyName = "";
$propertySchema = [];
foreach ($property->getAttributes() as $attribute)
{
if($attribute->getName() != SchemaDocumentField::class)
continue;
foreach($attribute->getArguments() as $key=>$value)
foreach($arguments as $key=>$value)
{
if($key == "Name")
switch($key)
{
case "Name":
$propertyName = $value;
}
elseif($key == "Child")
{
$propertySchema["#"] = [
"@comment" => $value->Comment,
"@valid_schemas" => $value->ValidSchemas,
];
break;
case "Existence":
if($value == null) continue;
$propertySchema["@existence"] = $value;
break;
case "Comment":
if($value == null) continue;
$propertySchema["@comment"] = $value;
break;
case "ValidSchemas":
if($value == null) continue;
$propertySchema["@valid_schemas"] = [];
foreach($value as $validSchema)
{
if (preg_match($classNameRegex, $validSchema))
if (preg_match(self::CLASS_NAME_REGEX, $validSchema))
$propertySchema["@valid_schemas"][] = URLHandling::GetURLForSchema($validSchema);
elseif (preg_match($urlRegex, $validSchema))
elseif (preg_match(self::URL_REGEX, $validSchema))
$propertySchema["@valid_schemas"][] = $validSchema;
else
$propertySchema["@valid_schemas"][] = "test123";
}
}
elseif($key == "Existance")
{
$propertySchema["#"] = $value->value;
}
elseif($key == "ValidSchemas")
{
$propertySchema["@valid_schemas"] = [];
foreach($value as $validSchema)
throw new \Exception("Invalid schema property: " . $validSchema);
}
break;
case "MaxSize":
if($value == PHP_INT_MIN) continue;
$propertySchema["@max_size"] = $value;
break;
case "MimeType":
if($value == null) continue;
$propertySchema["@mime_type"] = $value;
break;
case "Child":
if($value == null) continue;
$temp = json_decode(json_encode($value), true);
unset($temp['nodeType']);
unset($temp['attributes']);
unset($temp['name']);
unset($temp['args']);
$propertySchema["#"] = self::ProcessSchemaPropertyArguments($temp)[1];
break;
case "Children":
if($value == null) continue;
foreach($value as $child)
{
$temp = json_decode(json_encode($child), true);
unset($temp['nodeType']);
unset($temp['attributes']);
unset($temp['name']);
unset($temp['args']);
$propertySchema[$child->Name] = self::ProcessSchemaPropertyArguments($temp)[1];
}
break;
default:
throw new \Exception("unknown property: " . $key);
}
}
return [$propertyName, $propertySchema];
}
private static function ProcessSchemaProperties($reflection): array
{
if (preg_match($classNameRegex, $validSchema))
$propertySchema["@valid_schemas"][] = URLHandling::GetURLForSchema($validSchema);
elseif (preg_match($urlRegex, $validSchema))
$propertySchema["@valid_schemas"][] = $validSchema;
else
$propertySchema["@valid_schemas"][] = "test123";
}
}
elseif(self::VerifyField($key, $value, $validKeys[1]))
$schema = [];
foreach ($reflection->getProperties() as $property)
{
$propertySchema["@" . self::PascalCaseToSnakeCase(input: $key)] = $value;
}
}
}
$targetAttribute = null;
foreach ($property->getAttributes() as $attribute)
if($attribute->getName() == SchemaDocumentField::class)
$targetAttribute = $attribute;
if($targetAttribute == null)
throw new \Exception("required attribute does not exist");
$temp = self::ProcessSchemaPropertyArguments($targetAttribute->getArguments());
$propertyName = $temp[0];
$propertySchema = $temp[1];
if($propertyName == "")
throw new SchemaDocumentFieldNameUnsetException();
$schema["$propertyName"] = $propertySchema;
}
return $schema;
}
/**
* @throws SchemaDocumentFieldNameUnsetException
*/
private static function GenerateSchemaReflectionObject(ReflectionClass $reflection): array
{
$schema = [];
/*
* Schema "meta-data" from here...
*/
foreach($reflection->getAttributes()[0]->getArguments() as $key=>$value)
if(self::VerifyField($key, $value, self::GetValidKeys()[0]))
if($key != "Name")
$schema["@" . self::PascalCaseToSnakeCase(input: $key)] = $value;
/*
* Property handling from here...
*/
foreach(self::ProcessSchemaProperties($reflection) as $key=>$value)
$schema[$key] = $value;
return $schema;
}
public static function GenerateSchema(string $targetSchemaClassName): array
{
$reflection = new ReflectionClass(new $targetSchemaClassName());
return self::GenerateSchemaReflectionObject($reflection);
}
/**
* Generates the Schema using the SchemaBuilder::GenerateSchema() function, sets the http header to application/json, echos the schema as JSON, then dies.
*

Loading…
Cancel
Save