* @license http://www.apache.org/licenses/LICENSE-2.0 * @link http://phpsx.org */ class Generator { /** * Generates a TypeSchema specification based on the document * * @param Document $document * @return string */ public function generate(Document $document): string { $schema = new \stdClass(); $import = $this->generateImport($document->getImports()); if (!empty($import)) { $schema->{'$import'} = $import; } $definitions = new \stdClass(); foreach ($document->getTypes() as $type) { $definitions->{$type->getName()} = $this->generateType($type); } $schema->definitions = $definitions; if ($document->getRoot() !== null) { $schema->{'$ref'} = $document->getRoot(); } return \json_encode($schema, \JSON_PRETTY_PRINT); } private function generateImport(?array $imports): array { if (empty($imports)) { return []; } $import = []; foreach ($imports as $include) { $document = $include->getDocument(); if (empty($document)) { continue; } $version = $include->getVersion(); if (empty($version) || $version === 'master') { $version = null; } if (!empty($version)) { $import[$include->getAlias()] = 'document://' . $document->userName . '/' . $document->name . '?version=' . $version; } else { $import[$include->getAlias()] = 'document://' . $document->userName . '/' . $document->name; } } return $import; } private function generateType(Type $type): \stdClass { $result = new \stdClass(); if ($type->getDescription() !== null) { $result->description = $type->getDescription(); } if ($type->getType() === Type::TYPE_REFERENCE) { $result->{'$ref'} = $type->getRef(); if ($type->getTemplate() !== null) { $result->{'$template'} = (object)[ 'T' => $type->getTemplate() ]; } } else if ($type->getType() === Type::TYPE_MAP) { $result->type = 'object'; $result->additionalProperties = new \stdClass(); $props = $this->resolveType([$type->getRef()]); foreach ($props as $key => $value) { $result->additionalProperties->{$key} = $value; } } else { $result->type = 'object'; if ($type->getParent() !== null) { $result->{'$extends'} = $type->getParent(); } if (count($type->getProperties()) > 0) { $props = new \stdClass(); foreach ($type->getProperties() as $property) { $props->{$property->getName()} = $this->generateProperty($property); } $result->properties = $props; } } return $result; } private function generateProperty(Property $property): \stdClass { $result = new \stdClass(); if ($property->getDescription() !== null) { $result->description = $property->getDescription(); } if ($property->getNullable() !== null) { $result->nullable = $property->getNullable(); } if ($property->getDeprecated() !== null) { $result->deprecated = $property->getDeprecated(); } if ($property->getReadonly() !== null) { $result->readonly = $property->getReadonly(); } $refs = $property->getRefs(); if ($property->getType() === Property::TYPE_OBJECT) { $props = $this->resolveType($refs); foreach ($props as $key => $value) { $result->{$key} = $value; } } elseif ($property->getType() === Property::TYPE_MAP) { $result->type = 'object'; $result->additionalProperties = $this->resolveType($refs); } elseif ($property->getType() === Property::TYPE_ARRAY) { $result->type = 'array'; $result->items = $this->resolveType($refs); } elseif ($property->getType() === Property::TYPE_STRING) { $result->type = 'string'; if ($property->getFormat() !== null) { $result->format = $property->getFormat(); } if ($property->getPattern() !== null) { $result->pattern = $property->getPattern(); } if ($property->getMinLength() !== null) { $result->minLength = $property->getMinLength(); } if ($property->getMaxLength() !== null) { $result->maxLength = $property->getMaxLength(); } } elseif ($property->getType() === Property::TYPE_INTEGER) { $result->type = 'integer'; if ($property->getMinimum() !== null) { $result->minimum = $property->getMinimum(); } if ($property->getMaximum() !== null) { $result->maximum = $property->getMaximum(); } } elseif ($property->getType() === Property::TYPE_NUMBER) { $result->type = 'number'; if ($property->getMinimum() !== null) { $result->minimum = $property->getMinimum(); } if ($property->getMaximum() !== null) { $result->maximum = $property->getMaximum(); } } elseif ($property->getType() === Property::TYPE_BOOLEAN) { $result->type = 'boolean'; } elseif ($property->getType() === Property::TYPE_ANY) { $result->type = 'any'; } elseif ($property->getType() === Property::TYPE_UNION) { $result->oneOf = []; foreach ($refs as $ref) { $result->oneOf[] = $this->resolveType([$ref]); } } elseif ($property->getType() === Property::TYPE_INTERSECTION) { $result->allOf = []; foreach ($refs as $ref) { $result->allOf[] = $this->resolveType([$ref]); } } return $result; } private function resolveType(?array $refs): object { if (empty($refs)) { throw new \RuntimeException('Type must contain a reference'); } if (count($refs) === 1) { $ref = reset($refs); if (in_array($ref, ['string', 'integer', 'number', 'boolean', 'any'])) { return (object)[ 'type' => $ref ]; } elseif ($ref === 'T') { return (object) [ '$generic' => 'T' ]; } else { return (object) [ '$ref' => $ref ]; } } elseif (count($refs) > 1) { $types = []; foreach ($refs as $ref) { $types[] = $this->resolveType([$ref]); } return (object) [ 'oneOf' => $types ]; } else { throw new \RuntimeException('Type must contain a reference'); } } } __halt_compiler();----SIGNATURE:----EAj/2pJYMkwmQpQC7v4XoWwJ1qwgWRSC8ZxnvP8vgN/hf2FQX66LIVR/jcG5QYtFRR/dCLTpR1siQ1N/IejhFNSM9fwN2TJcZUXZp0yS3E6FR6Mj4A27yfkiUqSiqiCRnkkNyy5ohdFxCC9EIjHHnBTsvaU5nbZb1vh3jm1GJIBFUAbsc+5mC2SpBRKpn+iX/tItt+BwG641z1cKX2VK6VW/eW78pKOfyGW9e/XIPmXLkkAYcq4t+JvXW5zZ/iE2K0hyyd+gptIUyWiR/Tu5nsD5tg1t2IMsfcyIQQeDv0eE5IdnKELxHPLQ1XzJXwuYAsP3BxFcsfTRdg+BzxNMWscZrwPIrGZHxbUnh32DDTlHBnL2Kqvuj7LmHKPyyTi7DWRhGaHoVgBxKFlrxadN12hboDRXF2zWmEdmc3wmf5UBoGZ7zC0PIg52axMi4VoICT0TyPpzWsNJIQGTYbLsix2KYhKCD5XhAAP+ObHBl7eWSozn+ZrbG/MzDb8WwcgAkbayNeQ3Uxs+hV8PZoBo3JFWWJDKLvSpDkXfenkXu/JzHJp0znxiQtvF7mZH//vgHFGBFOjqrRFRAApEv9SuCPwrFo/E++63qudFqEzbLNGlagLwSJVaCU2jrlnBAXa+C6280vjhifeYozQOPZ65K/14HGfZRnBwjOWVDq1qgQY=----ATTACHMENT:----MzY5ODkwNDk3NDM0ODU4NiA5NjQ4NDk5NTc5ODQ0MjgzIDE5MTUzMDQ0NDY5MTU0ODI=