Skip to content

Commit

Permalink
update server gen
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskapp committed Aug 18, 2024
1 parent 806765b commit 56e5f45
Show file tree
Hide file tree
Showing 33 changed files with 583 additions and 181 deletions.
146 changes: 89 additions & 57 deletions src/Generator/Server/PHP.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
namespace PSX\Api\Generator\Server;

use PSX\Api\Generator\Server\Dto\File;
use PSX\Api\Operation\ArgumentInterface;
use PSX\Api\SpecificationInterface;
use PSX\Api\OperationInterface;
use PSX\Schema\Generator;
use PSX\Schema\GeneratorInterface as SchemaGeneratorInterface;

Expand All @@ -37,7 +36,10 @@ class PHP extends ServerAbstract
{
protected function newGenerator(): SchemaGeneratorInterface
{
return new Generator\Php();
$config = new Generator\Config();
$config->put(Generator\Config::NAMESPACE, 'App\\Model');

return new Generator\Php($config);
}

protected function getControllerPath(): string
Expand All @@ -50,82 +52,112 @@ protected function getModelPath(): string
return 'src/Model';
}

protected function buildControllerFileName(string $name): string
protected function getFileExtension(): string
{
return $this->normalizer->file($name);
return 'php';
}

protected function buildFolderName(string $name): string
protected function getFileContent(string $code, string $identifier): string
{
$comment = '/**' . "\n";
$comment.= ' * ' . $identifier . ' automatically generated by SDKgen please do not edit this file manually' . "\n";
$comment.= ' * @see https://sdkgen.app' . "\n";
$comment.= ' */' . "\n";

return '<?php' . "\n" . $comment . "\n" . $code;
}

protected function buildControllerFileName(string $name): string
{
return $this->normalizer->file($name);
}

protected function getFileExtension(): string
protected function buildFolderName(string $name): string
{
return 'php';
return $this->normalizer->file($name);
}

protected function generateControllerFile(File $file, SpecificationInterface $specification): string
protected function generateHeader(File $file, array $imports): string
{
$controllerClass = $this->buildControllerClass($file);
$controllerClass = $this->normalizer->class($file->getName());

$controller = '<?php' . "\n";
$controller = 'namespace App\Controller;' . "\n";
$controller.= "\n";
$controller.= 'namespace App\Controller;' . "\n";

foreach ($imports as $className) {
$controller.= 'use App\\Model\\' . $className . ';' . "\n";
}

$controller.= 'use PSX\Api\Attribute\Body;' . "\n";
$controller.= 'use PSX\Api\Attribute\Delete;' . "\n";
$controller.= 'use PSX\Api\Attribute\Get;' . "\n";
$controller.= 'use PSX\Api\Attribute\Param;' . "\n";
$controller.= 'use PSX\Api\Attribute\Patch;' . "\n";
$controller.= 'use PSX\Api\Attribute\Path;' . "\n";
$controller.= 'use PSX\Api\Attribute\Post;' . "\n";
$controller.= 'use PSX\Api\Attribute\Put;' . "\n";
$controller.= 'use PSX\Api\Attribute\Query;' . "\n";
$controller.= 'use PSX\Api\Attribute\StatusCode;' . "\n";
$controller.= 'use PSX\Framework\Controller\ControllerAbstract;' . "\n";
$controller.= "\n";
$controller.= 'class ' . $controllerClass . ' extends ControllerAbstract' . "\n";
$controller.= '{' . "\n";

foreach ($file->getOperations() as $operationName => $operation) {
$method = ucfirst(strtolower($operation->getMethod()));

$args = [];
foreach ($operation->getArguments()->getAll() as $argumentName => $argument) {
$rawName = $argumentName;
$variableName = $this->normalizer->argument($argumentName);
$type = $this->newType($argument->getSchema(), $specification->getDefinitions());

if ($argument->getIn() === ArgumentInterface::IN_PATH) {
if ($rawName === $variableName) {
$args[] = '#[Param] ' . $type->type . ' $' . $variableName;
} else {
$args[] = '#[Param(\'' . $rawName . '\')] ' . $type->type . ' $' . $variableName;
}
} elseif ($argument->getIn() === ArgumentInterface::IN_QUERY) {
if ($rawName === $variableName) {
$args[] = '#[Query] ' . $type->type . ' $' . $variableName;
} else {
$args[] = '#[Query(\'' . $rawName . '\')] ' . $type->type . ' $' . $variableName;
}
} elseif ($argument->getIn() === ArgumentInterface::IN_HEADER) {
if ($rawName === $variableName) {
$args[] = '#[Header] ' . $type->type . ' $' . $variableName;
} else {
$args[] = '#[Header(\'' . $rawName . '\')] ' . $type->type . ' $' . $variableName;
}
} elseif ($argument->getIn() === ArgumentInterface::IN_BODY) {
$args[] = '#[Body] ' . $type->type . ' $' . $variableName;
}
}

$type = $this->newType($operation->getReturn()->getSchema(), $specification->getDefinitions());

$controller.= ' #[' . $method . ']' . "\n";
$controller.= ' #[Path(\'' . $operation->getPath() . '\')]' . "\n";
$controller.= ' #[StatusCode(' . $operation->getReturn()->getCode() . ')]' . "\n";
$controller.= ' public function ' . $operationName . '(' . implode(', ', $args) . '): ' . $type->type . ' {' . "\n";
$controller.= ' // @TODO implement method' . "\n";
$controller.= ' }' . "\n";
$controller.= "\n";
}
return $controller;
}

$controller.= '}' . "\n";
protected function generateFooter(File $file): string
{
$controller = '}' . "\n";

return $controller;
}

private function buildControllerClass(File $file): string
protected function generateArgumentPath(string $rawName, string $variableName, string $type): string
{
if ($rawName === $variableName) {
return '#[Param] ' . $type . ' $' . $variableName;
} else {
return '#[Param(\'' . $rawName . '\')] ' . $type . ' $' . $variableName;
}
}

protected function generateArgumentQuery(string $rawName, string $variableName, string $type): string
{
if ($rawName === $variableName) {
return '#[Query] ' . $type . ' $' . $variableName;
} else {
return '#[Query(\'' . $rawName . '\')] ' . $type . ' $' . $variableName;
}
}

protected function generateArgumentHeader(string $rawName, string $variableName, string $type): string
{
if ($rawName === $variableName) {
return '#[Header] ' . $type . ' $' . $variableName;
} else {
return '#[Header(\'' . $rawName . '\')] ' . $type . ' $' . $variableName;
}
}

protected function generateArgumentBody(string $variableName, string $type): string
{
return '#[Body] ' . $type . ' $' . $variableName;
}

protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $returnType): string
{
return $this->normalizer->class($file->getName());
$methodName = ucfirst(strtolower($operation->getMethod()));

$method = ' #[' . $methodName . ']' . "\n";
$method.= ' #[Path(\'' . $operation->getPath() . '\')]' . "\n";
$method.= ' #[StatusCode(' . $operation->getReturn()->getCode() . ')]' . "\n";
$method.= ' public function ' . $operationName . '(' . implode(', ', $arguments) . '): ' . $returnType . "\n";
$method.= ' {' . "\n";
$method.= ' // @TODO implement method' . "\n";
$method.= ' }' . "\n";
$method.= "\n";

return $method;
}
}
82 changes: 80 additions & 2 deletions src/Generator/Server/ServerAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use PSX\Api\Generator\Server\Dto\File;
use PSX\Api\Generator\Server\Dto\Folder;
use PSX\Api\GeneratorInterface;
use PSX\Api\Operation\ArgumentInterface;
use PSX\Api\OperationInterface;
use PSX\Api\SpecificationInterface;
use PSX\Schema\DefinitionsInterface;
Expand All @@ -39,9 +40,12 @@
use PSX\Schema\GeneratorInterface as SchemaGeneratorInterface;
use PSX\Schema\Schema;
use PSX\Schema\Type\AnyType;
use PSX\Schema\Type\ArrayType;
use PSX\Schema\Type\IntersectionType;
use PSX\Schema\Type\MapType;
use PSX\Schema\Type\ReferenceType;
use PSX\Schema\Type\StructType;
use PSX\Schema\Type\UnionType;
use PSX\Schema\TypeFactory;
use PSX\Schema\TypeInterface;
use Twig\Environment;
Expand Down Expand Up @@ -132,10 +136,21 @@ private function generateRecursive(Folder $folder, Chunks $chunks, Specification

abstract protected function getControllerPath(): string;
abstract protected function getModelPath(): string;
abstract protected function buildControllerFileName(string $name): string;
abstract protected function generateControllerFile(File $file, SpecificationInterface $specification): string;
abstract protected function getFileExtension(): string;

abstract protected function generateHeader(File $file, array $imports): string;
abstract protected function generateFooter(File $file): string;
abstract protected function generateArgumentPath(string $rawName, string $variableName, string $type): string;
abstract protected function generateArgumentQuery(string $rawName, string $variableName, string $type): string;
abstract protected function generateArgumentHeader(string $rawName, string $variableName, string $type): string;
abstract protected function generateArgumentBody(string $variableName, string $type): string;
abstract protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $returnType): string;

protected function buildControllerFileName(string $name): string
{
return $name;
}

protected function buildFolderName(string $name): string
{
return $name;
Expand Down Expand Up @@ -191,6 +206,69 @@ protected function generateSchema(DefinitionsInterface $definitions, Generator\C
}
}

private function generateControllerFile(File $file, SpecificationInterface $specification): string
{
$controller = '';
$imports = [];

foreach ($file->getOperations() as $operationName => $operation) {
$args = [];
foreach ($operation->getArguments()->getAll() as $argumentName => $argument) {
$rawName = $argumentName;
$variableName = $this->normalizer->argument($argumentName);
$type = $this->newType($argument->getSchema(), $specification->getDefinitions());

if ($argument->getIn() === ArgumentInterface::IN_PATH) {
$args[] = $this->generateArgumentPath($rawName, $variableName, $type->type);
} elseif ($argument->getIn() === ArgumentInterface::IN_QUERY) {
$args[] = $this->generateArgumentQuery($rawName, $variableName, $type->type);
} elseif ($argument->getIn() === ArgumentInterface::IN_HEADER) {
$args[] = $this->generateArgumentHeader($rawName, $variableName, $type->type);
} elseif ($argument->getIn() === ArgumentInterface::IN_BODY) {
$args[] = $this->generateArgumentBody($variableName, $type->type);
}

$this->resolveImport($argument->getSchema(), $imports);
}

$type = $this->newType($operation->getReturn()->getSchema(), $specification->getDefinitions());

$this->resolveImport($operation->getReturn()->getSchema(), $imports);

$controller.= $this->generateMethod($operationName, $operation, $args, $type->type);
}

$result = $this->generateHeader($file, $imports);
$result.= $controller;
$result.= $this->generateFooter($file);

return $this->getFileContent($result, $file->getName());
}

private function resolveImport(TypeInterface $type, array &$imports): void
{
if ($type instanceof ReferenceType) {
$imports[$this->normalizer->file($type->getRef())] = $this->normalizer->class($type->getRef());
if ($type->getTemplate()) {
foreach ($type->getTemplate() as $typeRef) {
$imports[$this->normalizer->file($typeRef)] = $this->normalizer->class($typeRef);
}
}
} elseif ($type instanceof MapType && $type->getAdditionalProperties() instanceof TypeInterface) {
$this->resolveImport($type->getAdditionalProperties(), $imports);
} elseif ($type instanceof ArrayType && $type->getItems() instanceof TypeInterface) {
$this->resolveImport($type->getItems(), $imports);
} elseif ($type instanceof UnionType && $type->getOneOf()) {
foreach ($type->getOneOf() as $item) {
$this->resolveImport($item, $imports);
}
} elseif ($type instanceof IntersectionType) {
foreach ($type->getAllOf() as $item) {
$this->resolveImport($item, $imports);
}
}
}

protected function getFileName(string $identifier): string
{
$identifier = $this->generator->getNormalizer()->file($identifier);
Expand Down
Loading

0 comments on commit 56e5f45

Please sign in to comment.