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

Détermine l'IRI d'une ressource avant de mapper ses opérations.

parent ecd30eee
......@@ -327,10 +327,22 @@ final class ModelGenerator
}
$operations = [];
$pathParser = new PathParser($resourceMeta, $properties);
$pathParser = new PathParser($properties);
foreach ($resourceMeta->getOperations() as $operation) {
$mapper = new OperationMapper($this->typeFactory, $this->serializationMapperFactory, $pathParser, $operation);
$opsMeta = $resourceMeta->getOperations();
if (!$opsMeta) {
return null;
}
if (isset($opsMeta['getitem'])) {
$get = $opsMeta['getitem'];
$iri = $pathParser->parse($get->getPath(), $get->getRequirements());
} else {
$iri = null;
}
foreach ($opsMeta as $operation) {
$mapper = new OperationMapper($this->typeFactory, $this->serializationMapperFactory, $pathParser, $operation, $iri);
$operations[] = $mapper();
}
......@@ -338,6 +350,6 @@ final class ModelGenerator
return null;
}
return new Repository($resourceMeta, $defaultRepr, $identifier, $operations);
return new Repository($resourceMeta, $defaultRepr, $identifier, $iri, $operations);
}
}
......@@ -57,10 +57,11 @@ final class Repository extends ClassType
* @param ClassName $resource
* @param Type $resourceType
* @param Property $identifier
* @param Path|null $iri
* @param Operation[] $operations
* @param string $description
*/
public function __construct(ClassName $resource, Type $resourceType, Property $identifier, array $operations, string $description = '')
public function __construct(ClassName $resource, Type $resourceType, Property $identifier, ?Path $iri, array $operations, string $description = '')
{
parent::__construct(
$resource->getBaseName() . 'Repository',
......@@ -73,15 +74,12 @@ final class Repository extends ClassType
foreach ($operations as $operation) {
$this->operations[$operation->getName()] = $operation;
if ($operation->isGetItem()) {
$this->iri = $operation->getPath();
}
}
ksort($this->operations);
$this->resourceType = $resourceType;
$this->identifier = $identifier;
$this->iri = $iri;
}
/**
......
......@@ -25,7 +25,6 @@ use Irstea\NgModelGeneratorBundle\Models\Types\BuiltinType;
use Irstea\NgModelGeneratorBundle\Models\Types\Reference;
use Irstea\NgModelGeneratorBundle\Models\Types\Resources\Representation;
use Irstea\NgModelGeneratorBundle\Models\Types\Type;
use Irstea\NgModelGeneratorBundle\TypescriptHelper;
/**
* Class Operation.
......@@ -81,21 +80,43 @@ final class Operation implements \IteratorAggregate, \JsonSerializable
}
/**
* @return bool
* Get path.
*
* @return Path
*/
public function isGetItem(): bool
public function getPath(): ?Path
{
return $this->name === 'get';
return $this->path;
}
/**
* Get path.
* Get parameters.
*
* @return Path
* @return Parameter[]
*/
public function getPath(): ?Path
public function getParameters(): array
{
return $this->path;
return $this->parameters;
}
/**
* Get returnType.
*
* @return Type
*/
public function getReturnType(): Type
{
return $this->returnType;
}
/**
* Get body.
*
* @return string[]
*/
public function getBody(): array
{
return $this->body;
}
/**
......@@ -116,34 +137,6 @@ final class Operation implements \IteratorAggregate, \JsonSerializable
return $type instanceof Representation ? $type : null;
}
/**
* @return string
*/
public function getDeclaration(): string
{
$decl = sprintf(
"public %s(%s): Observable<%s> {\n%s\n}",
$this->name,
implode(
', ',
array_map(
function (Parameter $p): string {
return $p->getDeclaration();
},
$this->parameters
)
),
$this->returnType->getUsage(),
TypescriptHelper::indent(implode("\n", $this->body))
);
if ($this->description) {
$decl = sprintf("/**\n%s\n */\n%s", TypescriptHelper::indent($this->description, ' * '), $decl);
}
return $decl;
}
/**
* {@inheritdoc}
*/
......
......@@ -28,8 +28,10 @@ use Irstea\NgModelGeneratorBundle\Models\Types\Objects\InterfaceType;
use Irstea\NgModelGeneratorBundle\Models\Types\Objects\Property;
use Irstea\NgModelGeneratorBundle\Models\Types\Operations\Operation;
use Irstea\NgModelGeneratorBundle\Models\Types\Operations\Parameter;
use Irstea\NgModelGeneratorBundle\Models\Types\Operations\Path;
use Irstea\NgModelGeneratorBundle\Models\Types\Placeholder;
use Irstea\NgModelGeneratorBundle\Models\Types\Resources\Collection;
use Irstea\NgModelGeneratorBundle\Models\Types\Resources\IRI;
use Irstea\NgModelGeneratorBundle\Models\Types\Type;
use Irstea\NgModelGeneratorBundle\Models\Types\Union;
......@@ -50,6 +52,9 @@ final class OperationMapper
/** @var SerializationMapperFactoryInterface */
private $serializationMapperFactory;
/** @var Path|null */
private $iri;
/**
* OperationMapper constructor.
*
......@@ -57,17 +62,20 @@ final class OperationMapper
* @param SerializationMapperFactoryInterface $serializationMapperFactory
* @param PathParserInterface $pathParser
* @param OperationMetadata $operation
* @param Path|null $iri
*/
public function __construct(
TypeFactoryInterface $typeFactory,
SerializationMapperFactoryInterface $serializationMapperFactory,
PathParserInterface $pathParser,
OperationMetadata $operation
OperationMetadata $operation,
?Path $iri
) {
$this->typeFactory = $typeFactory;
$this->serializationMapperFactory = $serializationMapperFactory;
$this->operation = $operation;
$this->pathParser = $pathParser;
$this->iri = $iri;
}
/**
......@@ -86,26 +94,30 @@ final class OperationMapper
}
}
$path = $this->pathParser->parse($this->operation->getPath(), $this->operation->getRequirements());
$opParameters = $path->getParameters();
$options = $body = [];
$opParameters = $options = $body = [];
$callParameters = [TypescriptHelper::quoteString($this->operation->getMethod())];
$idParam = $path->getIdentifier();
if ($idParam) {
$body[] = sprintf(
'%s = %sRepository.getID(%s);',
$idParam->getName(),
$this->operation->getResource()->getBaseName(),
$idParam->getName()
);
}
$callPath = $path = $this->pathParser->parse($this->operation->getPath(), $this->operation->getRequirements());
$callParameters = [
TypescriptHelper::quoteString($this->operation->getMethod()),
'iri',
];
$iriParameterName = null;
if ($this->iri) {
$iriParameter = new Parameter('iri', Placeholder::get(sprintf('IRI<%s>', $this->operation->getClassName())));
$callPath = $path->buildUsing($this->iri, $iriParameter);
}
$body[] = sprintf('const iri = %s;', $path->getUsage());
if ($callPath === $this->iri) {
$opParameters[] = $iriParameter;
$iriParameterName = $iriParameter->getName();
$callParameters[] = $iriParameterName . ' as any';
} else {
foreach ($callPath->getParameters() as $parameter) {
$opParameters[] = $parameter;
}
$body[] = 'const path = ' . $callPath->getUsage() . ';';
$callParameters[] = 'path';
}
$denormalization = $this->operation->getDenormalization();
if ($denormalization) {
......@@ -133,7 +145,7 @@ final class OperationMapper
$returnType = $responseBody ?: Placeholder::get('HttpResponseBase');
$body[] = sprintf('return %s;', $this->buildClientCall($callParameters, $returnType));
$body[] = sprintf('return %s;', $this->buildClientCall($callParameters, $returnType, $iriParameterName));
return new Operation(
$this->operation->getName(),
......@@ -167,12 +179,13 @@ final class OperationMapper
}
/**
* @param array $callParameters
* @param Type $returnType
* @param array $callParameters
* @param Type $returnType
* @param string|null $iriParameterName
*
* @return string
*/
private function buildClientCall(array $callParameters, Type $returnType): string
private function buildClientCall(array $callParameters, Type $returnType, ?string $iriParameterName): string
{
$clientCall = sprintf(
'this.client.request<%s>(%s)',
......@@ -188,14 +201,16 @@ final class OperationMapper
if ($opDef->isCreateItem()) {
return "this.cache.post($clientCall)";
}
if ($opDef->isGetItem()) {
return "this.cache.get(iri, () => $clientCall)";
}
if ($opDef->isUpdateItem()) {
return "this.cache.put(iri, $clientCall)";
}
if ($opDef->isDeleteItem()) {
return "this.cache.delete(iri, $clientCall)";
if ($iriParameterName) {
if ($opDef->isGetItem()) {
return "this.cache.get($iriParameterName, () => $clientCall)";
}
if ($opDef->isUpdateItem()) {
return "this.cache.put($iriParameterName, $clientCall)";
}
if ($opDef->isDeleteItem()) {
return "this.cache.delete($iriParameterName, $clientCall)";
}
}
return $clientCall;
......@@ -270,7 +285,7 @@ final class OperationMapper
$this->typeFactory->add($filterName, $filterType);
$body = ["const $varName: { [name: string]: string | string[] } = {};"];
$body[] = "if (typeof params === 'object') {";
$body[] = "if (params && typeof params === 'object') {";
foreach ($filterProperties as $property) {
$assignation = sprintf(
' %s = %s;',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment