diff --git a/src/Models/Types/AbstractType.php b/src/Models/Types/AbstractType.php index d0954072376db5a79ec8ff49a32f3e87ed05d10b..6a702bfe32092f94d3b472451a1632f9036d5b0d 100644 --- a/src/Models/Types/AbstractType.php +++ b/src/Models/Types/AbstractType.php @@ -54,7 +54,7 @@ abstract class AbstractType implements Type /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { throw new DomainException('cannot type-check a ' . \get_class($this)); } diff --git a/src/Models/Types/Alias.php b/src/Models/Types/Alias.php index 210c3f8344bc994d494e9105ff7bbda3d8a1a23b..c0a581b216ba1de4820621ce4f6e0812460bce82 100644 --- a/src/Models/Types/Alias.php +++ b/src/Models/Types/Alias.php @@ -64,9 +64,9 @@ final class Alias extends AbstractType implements Declaration /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { - return $this->target->checkType($expr); + return $this->target->checkType($expr, $explicit); } /** diff --git a/src/Models/Types/ArrayType.php b/src/Models/Types/ArrayType.php index 3527d4c1b3ce73373d85301d168146173ab1db58..229ee245a8a6572bc2601c6bc88671c6a7df90be 100644 --- a/src/Models/Types/ArrayType.php +++ b/src/Models/Types/ArrayType.php @@ -56,8 +56,13 @@ class ArrayType extends AbstractCollection /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { - return sprintf('Array.isArray(%s)', $expr); + return sprintf( + '(Array.isArray(%s) && %s.findIndex(x => !%s) === -1)', + $expr, + $expr, + $this->valueType->checkType('x', $explicit) + ); } } diff --git a/src/Models/Types/BuiltinType.php b/src/Models/Types/BuiltinType.php index 37aeaafa71ca1e442bc93c98f93bfa4d5f94c9f6..8c735517dbb78c97b23438b5f4422ffe6ac9d67d 100644 --- a/src/Models/Types/BuiltinType.php +++ b/src/Models/Types/BuiltinType.php @@ -64,7 +64,7 @@ class BuiltinType extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return sprintf('(typeof %s === %s)', $expr, TypescriptHelper::quoteString($this->name)); } diff --git a/src/Models/Types/Objects/AnonymousObject.php b/src/Models/Types/Objects/AnonymousObject.php index 29df040bf7fa3c2a493fbf6964432703f0ad1da4..91d98cebecc62a795363013751d1a0738b263c27 100644 --- a/src/Models/Types/Objects/AnonymousObject.php +++ b/src/Models/Types/Objects/AnonymousObject.php @@ -102,9 +102,22 @@ class AnonymousObject extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { - return BuiltinType::get('object')->checkType($expr); + $tests = [BuiltinType::get('object')->checkType($expr, false)]; + + /** @var Property $property */ + foreach ($this->properties as $property) { + $tpl = $property->isNullable() ? '(!(%s in %s) || %s)' : '(%s in %s && %s)'; + $tests[] = sprintf( + $tpl, + TypescriptHelper::quoteString($property->getName()), + $expr, + $property->getType()->checkType($property->getUsage($expr), false) + ); + } + + return '(' . implode("\n && ", $tests) . ')'; } /** diff --git a/src/Models/Types/Objects/ClassType.php b/src/Models/Types/Objects/ClassType.php index 44b568cd6be276a359d251c5bf7af81b5581734b..b799fc8325e803b6f449f0c835c81226b8a4932e 100644 --- a/src/Models/Types/Objects/ClassType.php +++ b/src/Models/Types/Objects/ClassType.php @@ -35,7 +35,7 @@ class ClassType extends AbstractHierarchicalObject /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return sprintf('(%s instanceof %s)', $expr, $this->name); } diff --git a/src/Models/Types/Objects/InterfaceType.php b/src/Models/Types/Objects/InterfaceType.php index c9dd009187f0906242941e2b1798e719991f4933..906412aa4a4a4cd1744c5459c1f013a591ad003e 100644 --- a/src/Models/Types/Objects/InterfaceType.php +++ b/src/Models/Types/Objects/InterfaceType.php @@ -19,8 +19,6 @@ namespace Irstea\NgModelGeneratorBundle\Models\Types\Objects; -use Irstea\NgModelGeneratorBundle\TypescriptHelper; - /** * Class InterfaceType. */ @@ -33,25 +31,4 @@ class InterfaceType extends AbstractHierarchicalObject { return 'interface'; } - - /** - * {@inheritdoc} - */ - public function checkType(string $expr): string - { - $tests = [parent::checkType($expr)]; - /** @var Property $property */ - foreach ($this->getProperties() as $property) { - if (!$property->isNullable()) { - $tests[] = sprintf( - '(%s in %s && %s)', - TypescriptHelper::quoteString($property->getName()), - $expr, - $property->getType()->checkType($property->getUsage($expr)) - ); - } - } - - return '(' . implode("\n && ", $tests) . ')'; - } } diff --git a/src/Models/Types/Objects/Repository.php b/src/Models/Types/Objects/Repository.php index 64e6fb063f2c28f658ef488ae5ce70b26266f277..166e3c9e20ede0bb105618b904a7c744c919949d 100644 --- a/src/Models/Types/Objects/Repository.php +++ b/src/Models/Types/Objects/Repository.php @@ -142,7 +142,7 @@ public static isValidResource(data: any): data is %s { CODE , $this->rootType->getUsage(), - $this->rootType->checkType('data') + $this->rootType->checkType('data', true) ); // Extraction d'ID diff --git a/src/Models/Types/Reference.php b/src/Models/Types/Reference.php index d49abfdc70f6f3174c6017433e9e12dace96ea1a..c469289e7d7636f5ade75e1e971b6c5403b65f77 100644 --- a/src/Models/Types/Reference.php +++ b/src/Models/Types/Reference.php @@ -86,9 +86,9 @@ class Reference extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { - return $this->dereference()->checkType($expr); + return $this->dereference()->checkType($expr, $explicit); } /** diff --git a/src/Models/Types/Resources/AtType.php b/src/Models/Types/Resources/AtType.php index 800094175aeba85602342b2492f4d62c8499e1ad..e9b3fa127eda38fa1de89bbbf73c35b5809f6498 100644 --- a/src/Models/Types/Resources/AtType.php +++ b/src/Models/Types/Resources/AtType.php @@ -73,7 +73,7 @@ final class AtType extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { $names = $this->getNames(); if (\count($names) === 1) { diff --git a/src/Models/Types/Resources/IRI.php b/src/Models/Types/Resources/IRI.php index 8598d68c384ed1360d9505cd54fbbf9f1328701c..b3ed4f154110296d1d9cf7f13f5652afe260a7c6 100644 --- a/src/Models/Types/Resources/IRI.php +++ b/src/Models/Types/Resources/IRI.php @@ -72,7 +72,7 @@ final class IRI extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return sprintf('(%s)', implode( ' || ', diff --git a/src/Models/Types/Resources/Representation.php b/src/Models/Types/Resources/Representation.php new file mode 100644 index 0000000000000000000000000000000000000000..81b4bc14db4838449d963cad2e2c1af90973c398 --- /dev/null +++ b/src/Models/Types/Resources/Representation.php @@ -0,0 +1,72 @@ +<?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\Types\Resources; + +use Irstea\NgModelGeneratorBundle\Models\PHPClass; +use Irstea\NgModelGeneratorBundle\Models\Types\Objects\InterfaceType; +use Irstea\NgModelGeneratorBundle\Models\Types\Type; + +/** + * Class Representation. + */ +final class Representation extends InterfaceType +{ + /** @var PHPClass */ + private $resource; + + /** + * {@inheritdoc} + */ + public function __construct(PHPClass $resource, string $name, ?Type $parent, $properties = [], string $description = '', array $children = []) + { + parent::__construct($name, $parent, $properties, $description, $children); + $this->resource = $resource; + } + + /** + * Get resource. + * + * @return PHPClass + */ + public function getResource(): PHPClass + { + return $this->resource; + } + + /** + * @return string + */ + public function getResourceName(): string + { + return $this->resource->getBaseName(); + } + + /** + * {@inheritdoc} + */ + public function checkType(string $expr, bool $explicit = false): string + { + if (!$explicit) { + return sprintf('%sRepository.isValidResource(%s)', $this->getResourceName(), $expr); + } + + return parent::checkType($expr, false); + } +} diff --git a/src/Models/Types/Resources/UUID.php b/src/Models/Types/Resources/UUID.php index 9eebc981245c1c534a76fd72caebfcd55a79757f..e4ea74aa0781c01c855f37eb0bd8ffbad6966c6e 100644 --- a/src/Models/Types/Resources/UUID.php +++ b/src/Models/Types/Resources/UUID.php @@ -52,7 +52,7 @@ final class UUID extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return "isUUID($expr)"; } diff --git a/src/Models/Types/StringConst.php b/src/Models/Types/StringConst.php index e68ef1577b53c88f21636bbd3e11ba70f8818192..8f780cc518f65a7e648b1099934d6df84c459fee 100644 --- a/src/Models/Types/StringConst.php +++ b/src/Models/Types/StringConst.php @@ -60,7 +60,7 @@ final class StringConst extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return sprintf('(%s === %s)', $expr, $this->getUsage()); } diff --git a/src/Models/Types/Type.php b/src/Models/Types/Type.php index 90a4606b027523c625cf935e3562d9f441a959dd..6d651078dadfc0522bd54da8f5ca087e3389d834 100644 --- a/src/Models/Types/Type.php +++ b/src/Models/Types/Type.php @@ -38,8 +38,9 @@ interface Type extends \IteratorAggregate, \JsonSerializable /** * @param string $expr + * @param bool $explicit * * @return string */ - public function checkType(string $expr): string; + public function checkType(string $expr, bool $explicit = false): string; } diff --git a/src/Models/Types/Union.php b/src/Models/Types/Union.php index 8a8198fe58039784a2182b2eacb2476b9bee3c51..c0028e2642f423488227876b0e11e767f84d4a64 100644 --- a/src/Models/Types/Union.php +++ b/src/Models/Types/Union.php @@ -75,11 +75,11 @@ final class Union extends AbstractType /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { $checks = []; foreach ($this->types as $type) { - $checks[$type->checkType($expr)] = true; + $checks[$type->checkType($expr, $explicit)] = true; } return '(' . implode(' || ', array_keys($checks)) . ')'; diff --git a/src/Models/Types/Unresolved.php b/src/Models/Types/Unresolved.php index 2bd16c3755d988074bbfb16e56d9de208eb3602a..d7a491501bf4f871f6346727a13acdc4858334f0 100644 --- a/src/Models/Types/Unresolved.php +++ b/src/Models/Types/Unresolved.php @@ -82,7 +82,7 @@ final class Unresolved implements Type /** * {@inheritdoc} */ - public function checkType(string $expr): string + public function checkType(string $expr, bool $explicit = false): string { return 'false /* unresolved */'; } diff --git a/src/SerializationMapper.php b/src/SerializationMapper.php index af257c96302d4c556bc10dc73cac0a4f42b37d79..c383376e574ad058092dc1b2a4e4ef14a1162a6c 100644 --- a/src/SerializationMapper.php +++ b/src/SerializationMapper.php @@ -29,12 +29,12 @@ use Irstea\NgModelGeneratorBundle\Models\Types\Alias; use Irstea\NgModelGeneratorBundle\Models\Types\ArrayType; use Irstea\NgModelGeneratorBundle\Models\Types\BuiltinType; use Irstea\NgModelGeneratorBundle\Models\Types\Objects\AnonymousObject; -use Irstea\NgModelGeneratorBundle\Models\Types\Objects\InterfaceType; use Irstea\NgModelGeneratorBundle\Models\Types\Objects\Property; use Irstea\NgModelGeneratorBundle\Models\Types\Placeholder; use Irstea\NgModelGeneratorBundle\Models\Types\Reference; use Irstea\NgModelGeneratorBundle\Models\Types\Resources\AtType; use Irstea\NgModelGeneratorBundle\Models\Types\Resources\IRI; +use Irstea\NgModelGeneratorBundle\Models\Types\Resources\Representation; use Irstea\NgModelGeneratorBundle\Models\Types\Type; use Irstea\NgModelGeneratorBundle\Models\Types\Union; use Symfony\Component\PropertyInfo\Type as APIType; @@ -218,7 +218,7 @@ final class SerializationMapper implements TypeFactoryInterface } } - return new InterfaceType($repr->getName(), $parent, $properties, $desc, $children); + return new Representation($resourceClass, $repr->getName(), $parent, $properties, $desc, $children); } /**