Commit e6c6363b authored by Guillaume Perréal's avatar Guillaume Perréal
Browse files

Refactoring massif.

parent a6a1317c
......@@ -17,20 +17,26 @@
* <https://www.gnu.org/licenses/>.
*/
namespace Irstea\NgModelGeneratorBundle\Models;
namespace Irstea\NgModelGeneratorBundle;
/**
* Interface TypeDeclaration.
* Class FQCN.
*/
interface Declaration
final class FQCN
{
/**
* @param string $fqcn
*
* @return string
*/
public function getName(): string;
public static function baseName(string $fqcn): string
{
$lastSep = strrpos($fqcn, '\\');
/**
* @return string
*/
public function getDeclaration(): string;
return $lastSep !== false ? substr($fqcn, $lastSep + 1) : $fqcn;
}
private function __construct()
{
}
}
<?php declare(strict_types=1);
/**
* Copyright (C) 2018 IRSTEA
* All rights reserved.
* @copyright 2018 IRSTEA
* @author guillaume.perreal
*/
namespace Irstea\NgModelGeneratorBundle\Iterators;
/**
* Class UniqueFilter
*/
final class UniqueFilter
{
/**
* @var array<string,bool>
*/
private $seen = [];
/**
* @param $value
*
* @return bool
*/
public function __invoke($value): bool
{
$key = is_object($value) ? spl_object_hash($value) : (string)$value;
if (isset($this->seen[$key])) {
return false;
}
$this->seen[$key] = true;
return true;
}
/**
*
*/
public function reset(): void {
$this->seen = [];
}
}
<?php declare(strict_types=1);
/*
* irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata.
* Copyright (C) 2018 IRSTEA
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License and the GNU
* Lesser General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
namespace Irstea\NgModelGeneratorBundle\Models;
use Irstea\NgModelGeneratorBundle\Models\Metadata\OperationMetadata;
use Irstea\NgModelGeneratorBundle\Models\Metadata\ResourceMetadata;
/**
* Class Context.
*/
final class Context
{
/**
* @var ResourceMetadata|null
*/
private $resource = null;
/**
* @var OperationMetadata|null
*/
private $operation = null;
/**
* @var string[]
*/
private $groups = [];
/**
* @var bool
*/
private $normalization = true;
/**
* @param ResourceMetadata $resource
*
* @return Context
*/
public function withResource(ResourceMetadata $resource): Context
{
$new = clone $this;
$new->resource = $resource;
return $new;
}
/**
* @param OperationMetadata $operation
*
* @return Context
*/
public function withOperation(OperationMetadata $operation): self
{
$new = clone $this;
$new->operation = $operation;
return $new;
}
/**
* @param array $groups
* @param bool $normalization
*
* @return Context
*/
public function withSerializerContext(array $groups, bool $normalization): self
{
$new = clone $this;
sort($groups);
$new->groups = $groups;
$new->normalization = $normalization;
return $new;
}
/**
* Get resource.
*
* @return ResourceMetadata|null
*/
public function getResource(): ?ResourceMetadata
{
return $this->resource;
}
/**
* Get operation.
*
* @return OperationMetadata|null
*/
public function getOperation(): ?OperationMetadata
{
return $this->operation;
}
/**
* Get groups.
*
* @return string[]
*/
public function getGroups(): array
{
return $this->groups;
}
/**
* Get normalization.
*
* @return bool
*/
public function isNormalization(): bool
{
return $this->normalization;
}
/**
* @return string
*/
public function getSuffix(): string
{
if (empty($this->groups)) {
return $this->isNormalization() ? 'Response' : 'Request';
}
return implode('', $this->groups);
}
/**
* @return string
*/
public function getKeySuffix(): string
{
return sha1($this->operation->getName() . $this->operation->getType() . ($this->isNormalization() ? 'Response' : 'Request'));
}
}
......@@ -27,15 +27,7 @@ trait NamedTrait
/**
* @var string
*/
private $name;
/**
* @param string $name
*/
private function setName(string $name): void
{
$this->name = $name;
}
protected $name;
/**
* @return string
......@@ -44,28 +36,4 @@ trait NamedTrait
{
return $this->name;
}
/**
* @return bool
*/
public function getUsage(): string
{
return $this->getName();
}
/**
* @return bool
*/
public function hasSimpleReference(): bool
{
return true;
}
/**
* @return string
*/
public function getEscapedName(): string
{
return preg_match('/^[a-z_][0-9a-z_]*$/i', $this->name) ? $this->name : "'{$this->name}'";
}
}
......@@ -68,12 +68,4 @@ final class CachedClientCall implements ClientCall
{
return sprintf($this->decorator, $this->innerCall->getCall());
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
return $this->innerCall->getIterator();
}
}
......@@ -22,7 +22,7 @@ namespace Irstea\NgModelGeneratorBundle\Models\Operations;
/**
* Class ClientCall.
*/
interface ClientCall extends \IteratorAggregate
interface ClientCall
{
/**
* @return Parameter[]
......
......@@ -20,6 +20,7 @@
namespace Irstea\NgModelGeneratorBundle\Models\Operations;
use Irstea\NgModelGeneratorBundle\Models\Types\Type;
use Irstea\NgModelGeneratorBundle\TypescriptHelper;
/**
* Class DirectClientCall.
......@@ -113,12 +114,14 @@ final class DirectClientCall implements ClientCall
*/
public function getReturnType(): string
{
$type = $this->responseBody ? $this->responseBody->getUsage() : 'HttpResponseBase';
if (!$this->responseBody) {
return 'HttpResponseBase';
}
if ($this->collection) {
return "HydraCollection<$type>";
return sprintf('HydraCollection<%s>', $this->responseBody->getUsage());
}
return $type;
return $this->responseBody->getUsage();
}
/**
......@@ -132,8 +135,8 @@ final class DirectClientCall implements ClientCall
}
$args = [
$this->quoteString($this->httpMethod),
$this->quoteString($this->httpPath, $this->pathParameters ? '`' : "'"),
TypescriptHelper::quoteString($this->httpMethod),
TypescriptHelper::quoteString($this->httpPath, $this->pathParameters ? '`' : "'"),
];
if ($options) {
......@@ -142,42 +145,4 @@ final class DirectClientCall implements ClientCall
return sprintf('this.client.request<%s>(%s)', $this->getReturnType(), implode(', ', $args));
}
/**
* @param string $str
* @param string $delim
*
* @return string
*/
private function quoteString(string $str, string $delim = "'"): string
{
if (strpos($str, $delim) !== false) {
if ($delim === "'" && strpos($str, '"') === false) {
$delim = '"';
} elseif ($delim === '"' && strpos($str, "'") === false) {
$delim = "'";
} else {
$str = str_replace($delim, '\\' . $delim, $str);
}
}
return $delim . $str . $delim;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
yield from $this->pathParameters;
if ($this->requestBody) {
yield $this->requestBody;
}
if ($this->queryParameters) {
yield $this->queryParameters;
}
if ($this->responseBody) {
yield $this->responseBody;
}
}
}
......@@ -22,7 +22,7 @@ namespace Irstea\NgModelGeneratorBundle\Models\Operations;
/**
* Class Operation.
*/
class Operation implements \IteratorAggregate
final class Operation
{
/**
* @var string
......@@ -48,6 +48,7 @@ class Operation implements \IteratorAggregate
/**
* Get name.
*
* @return string
*/
public function getName(): string
......@@ -55,9 +56,6 @@ class Operation implements \IteratorAggregate
return $this->name;
}
/**
* {@inheritdoc}
*/
public function getDeclaration(): string
{
$params = [];
......@@ -73,12 +71,4 @@ class Operation implements \IteratorAggregate
$this->clientCall->getCall()
);
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
yield $this->clientCall;
}
}
......@@ -25,7 +25,7 @@ use Irstea\NgModelGeneratorBundle\Models\Types\Type;
/**
* Class Parameter.
*/
class Parameter implements \IteratorAggregate
class Parameter
{
use NamedTrait;
......@@ -48,7 +48,7 @@ class Parameter implements \IteratorAggregate
*/
public function __construct(string $name, Type $type, bool $optional = false)
{
$this->setName($name);
$this->name = $name;
$this->type = $type;
}
......@@ -67,7 +67,7 @@ class Parameter implements \IteratorAggregate
*/
public function getDeclaration(): string
{
return sprintf('%s%s: %s', $this->getEscapedName(), $this->optional ? '?' : '', $this->type->getUsage());
return sprintf('%s%s: %s', $this->name, $this->optional ? '?' : '', $this->type->getUsage());
}
/**
......@@ -79,20 +79,4 @@ class Parameter implements \IteratorAggregate
{
return $this->optional;
}
/**
* {@inheritdoc}
*/
protected function doWalk(callable $walker, array &$seen = []): void
{
$this->type->walk($walker, $seen);
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
yield $this->type;
}
}
......@@ -19,7 +19,7 @@
namespace Irstea\NgModelGeneratorBundle\Models\Operations;
use Irstea\NgModelGeneratorBundle\Models\Types\Object;
use Irstea\NgModelGeneratorBundle\Models\Types\AnonymousObject;
use Irstea\NgModelGeneratorBundle\Models\Types\Type;
/**
......@@ -42,7 +42,7 @@ final class TransformedParameter extends Parameter
{
$components = [];
/** @var object $type */
/** @var AnonymousObject $type */
$type = $this->getType();
$paramName = $this->getName();
......
......@@ -20,23 +20,31 @@
namespace Irstea\NgModelGeneratorBundle\Models\Types;
/**
* Class Never.
* Class AbstractType.
*/
final class Never extends Type
abstract class AbstractType implements Type
{
/**
* @return Type
*/
public function dereference(): Type
{
return $this;
}
/**
* {@inheritdoc}
*/
public function mergeWith(Type $t): Type
public function getDeclaration(string $name): string
{
return $t;
return sprintf('export type %s = %s', $name, $this->getUsage());
}
/**
* {@inheritdoc}
*/
public function getUsage(): string
public function __toString()
{
return 'never';
return $this->getUsage();
}
}
......@@ -19,83 +19,109 @@
namespace Irstea\NgModelGeneratorBundle\Models\Types;
use Irstea\NgModelGeneratorBundle\Models\Declaration;
use Irstea\NgModelGeneratorBundle\Models\NamedTrait;
/**
* Class TypeDeclaration.
* Class AnonymousObject.
*/
abstract class TypeDeclaration extends Type implements Declaration
class AnonymousObject extends AbstractType implements Object
{
use NamedTrait;
use DecoratorTrait;
/** @var string */
private $description;
/**
* @var array<string,Property>
*/
private $properties = [];
/**
* TypeDeclaration constructor.
* Resource constructor.
*
* @param string $name
* @param Type $type
* @param string $description
* @param array<string,Property> $properties
*/
public function __construct(string $name, Type $type, string $description = '')
public function __construct(array $properties = [])
{
$this->setName($name);
$this->setDecorated($type);
$this->description = $description;
$this->properties = array_values($properties);
}
/**
* {@inheritdoc}
*/
public function getDeclaration(): string
public function getProperties(): array
{
$decl = sprintf('export %s;', $this->doGetDeclaration());
if ($this->description) {
$decl = "/**\n * " . implode("\n * ", explode("\n", $this->description)) . "\n */\n" . $decl;
}
return $decl;
return $this->properties;
}
/**
* @return string
* {@inheritdoc}
*/
abstract protected function doGetDeclaration(): string;
public function getUsage(): string
{
return $this->getDeclarationBody(false);
}
/**
* {@inheritdoc}
*/
public function getUsage(): string
final public function getDeclaration(string $name): string
{
return $this->getName();
return trim($this->getDeclarationHeader($name) . ' ' . $this->getDeclarationBody(true));
}
/**
* {@inheritdoc}
* @return string
*/
public function mergeWith(Type $t): Type
protected function getDeclarationHeader(string $name): string
{
if ($t === $this) {
return $this;
}
if ($t instanceof static && $this->getName() === $t->getName()) {
$this->setDecorated($this->getDecorated()->mergeWith($t->getDecorated()));
return '';
}
return $this;
/**
* @return string
*/
private function getDeclarationBody(bool $multiline): string
{
$body = array_merge(
$this->getPropertyDeclarations(),
$this->getMethodDeclarations()
);