diff --git a/src/Context.php b/src/Context.php index eeb6c3015c613b66dfbc962c3d2bc727f5dd1435..ac9cb04c3d4d5571b639f1c65d977d6dc017bf25 100644 --- a/src/Context.php +++ b/src/Context.php @@ -19,12 +19,14 @@ namespace Irstea\NgModelGeneratorBundle; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Class Context. */ class Context implements ContextInterface { - /** @var string */ + /** @var PHPClass */ private $rootClass; /** @var bool */ @@ -44,7 +46,7 @@ class Context implements ContextInterface * @param string[] $groups * @param \string[][] $defaultGroups */ - public function __construct(string $rootClass, array $defaultGroups, bool $normalization = false, array $groups = []) + public function __construct(PHPClass $rootClass, array $defaultGroups, bool $normalization = false, array $groups = []) { $this->rootClass = $rootClass; $this->defaultGroups = $defaultGroups; @@ -71,7 +73,7 @@ class Context implements ContextInterface } /** - * @param bool $normalization + * @param string[] $groups * * @return Context */ @@ -93,9 +95,9 @@ class Context implements ContextInterface /** * Get rootClass. * - * @return string + * @return PHPClass */ - public function getRootClass(): string + public function getRootClass(): PHPClass { return $this->rootClass; } @@ -117,12 +119,12 @@ class Context implements ContextInterface } /** - * @param string $className + * @param PHPClass $class * * @return string[] */ - public function getDefaultGroups(string $className): array + public function getDefaultGroups(PHPClass $class): array { - return $this->defaultGroups[$this->normalization ? 'normalization' : 'denormalization'][$className] ?? []; + return $this->defaultGroups[$this->normalization ? 'normalization' : 'denormalization'][$class->getFullName()] ?? []; } } diff --git a/src/ContextInterface.php b/src/ContextInterface.php index d03fdf91d82298f67f1c5ac8f7b6c86bd0becf37..0b02806664be49c2a382d3da70c971a96b29ee0f 100644 --- a/src/ContextInterface.php +++ b/src/ContextInterface.php @@ -19,6 +19,8 @@ namespace Irstea\NgModelGeneratorBundle; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Interface ContextInterface. */ @@ -32,7 +34,7 @@ interface ContextInterface public function withNormalization(bool $normalization): self; /** - * @param bool $normalization + * @param string[] $groups * * @return Context */ @@ -41,9 +43,9 @@ interface ContextInterface /** * Get rootClass. * - * @return string + * @return PHPClass */ - public function getRootClass(): string; + public function getRootClass(): PHPClass; /** * @return bool @@ -56,9 +58,9 @@ interface ContextInterface public function getGroups(): array; /** - * @param string $className + * @param PHPClass $class * * @return string[] */ - public function getDefaultGroups(string $className): array; + public function getDefaultGroups(PHPClass $class): array; } diff --git a/src/DefaultNamingStrategy.php b/src/DefaultNamingStrategy.php index 5f7ec0e802d7e27e49ed34e274ec9eea241bacec..656f8b0f48b94f6e0f530f688d98a0a8268ce473 100644 --- a/src/DefaultNamingStrategy.php +++ b/src/DefaultNamingStrategy.php @@ -19,6 +19,8 @@ namespace Irstea\NgModelGeneratorBundle; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Class DefaultNamingStrategy. */ @@ -27,7 +29,7 @@ final class DefaultNamingStrategy implements NamingStrategy /** * {@inheritdoc} */ - public function getName(ContextInterface $ctx, string $resourceClass): string + public function getName(ContextInterface $ctx, PHPClass $resourceClass): string { $parts = array_diff( $ctx->getGroups(), @@ -35,7 +37,7 @@ final class DefaultNamingStrategy implements NamingStrategy $ctx->getDefaultGroups($ctx->getRootClass()) ); - $baseName = FQCN::baseName($resourceClass); + $baseName = $resourceClass->getBaseName(); $shortPrefix = $ctx->isNormalization() ? '' : 'Put'; $fullPrefix = $ctx->isNormalization() ? 'Get' : 'Put'; @@ -46,7 +48,7 @@ final class DefaultNamingStrategy implements NamingStrategy array_unshift($parts, $shortPrefix . $baseName); } } else { - $rootBaseName = FQCN::baseName($ctx->getRootClass()); + $rootBaseName = $ctx->getRootClass()->getBaseName(); $rootGroup = $fullPrefix . $rootBaseName; if (\in_array($rootGroup, $parts, true)) { array_unshift($parts, $rootBaseName); diff --git a/src/Metadata/CachingMetadataFactory.php b/src/Metadata/CachingMetadataFactory.php index 4f527313244d5e0b17c094f81d6cb8cbfcc7f491..018e6568ded4183d388649c09a2487284285f1eb 100644 --- a/src/Metadata/CachingMetadataFactory.php +++ b/src/Metadata/CachingMetadataFactory.php @@ -21,6 +21,7 @@ namespace Irstea\NgModelGeneratorBundle\Metadata; use Doctrine\Common\Cache\ArrayCache; use Doctrine\Common\Cache\Cache; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; /** * Class CachingMetadataFactory. @@ -48,43 +49,46 @@ final class CachingMetadataFactory implements MetadataFactoryInterface /** * {@inheritdoc} */ - public function isResource(string $className): bool + public function isResource(PHPClass $class): bool { - return $this->inner->isResource($className); + return $this->inner->isResource($class); } /** * {@inheritdoc} */ - public function getResourceMetadata(string $className): ResourceMetadata + public function getResourceMetadata(PHPClass $class): ResourceMetadata { - return $this->memoize(__METHOD__, $className, function ($className) { - return $this->inner->getResourceMetadata($className)->setFactory($this); + return $this->memoize(__METHOD__, $class->getFullName(), function () use ($class) { + return $this->inner->getResourceMetadata($class)->setFactory($this); }); } /** * {@inheritdoc} */ - public function getOperations(string $className): array + public function getOperations(PHPClass $class): array { - return $this->memoize(__METHOD__, $className, [$this->inner, 'getOperations']); + return $this->memoize(__METHOD__, $class->getFullName(), function () use ($class) { + return $this->inner->getOperations($class); + }); } /** * {@inheritdoc} */ - public function getProperties(string $className, array $groups = []): array + public function getProperties(PHPClass $class, array $groups = []): array { sort($groups); - $key = $className . '::' . implode('-', $groups); + $key = $class->getFullName() . '::' . implode('-', $groups); - return $this->memoize(__METHOD__, $key, function () use ($className, $groups) { - return $this->inner->getProperties($className, $groups); + return $this->memoize(__METHOD__, $key, function () use ($class, $groups) { + return $this->inner->getProperties($class, $groups); }); } /** + * @param string $namespace * @param string $key * @param callable $compute * diff --git a/src/Metadata/MetadataFactory.php b/src/Metadata/MetadataFactory.php index 523a8b329167bbfba48cb01dfa5d74e179fc5ba8..95ebdd784c694a9cf9440eda50d20929d3cdbe6c 100644 --- a/src/Metadata/MetadataFactory.php +++ b/src/Metadata/MetadataFactory.php @@ -28,6 +28,7 @@ use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInte use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata as APIResourceMetadata; use ApiPlatform\Core\PathResolver\OperationPathResolverInterface; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; use Psr\Container\ContainerInterface; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; @@ -100,30 +101,27 @@ final class MetadataFactory implements MetadataFactoryInterface } /** - * @param string $className - * - * @return bool + * {@inheritdoc} */ - public function isResource(string $className): bool + public function isResource(PHPClass $class): bool { - return $this->resourceClassResolver->isResourceClass($className); + return $this->resourceClassResolver->isResourceClass($class->getFullName()); } /** - * @param string $className - * - * @return ResourceMetadata + * {@inheritdoc} */ - public function getResourceMetadata(string $className): ResourceMetadata + public function getResourceMetadata(PHPClass $class): ResourceMetadata { + $className = $class->getFullName(); $metadata = $this->resourceMetadataFactory->create($className); $classMeta = new \ReflectionClass($className); $parentClass = $classMeta->getParentClass(); return new ResourceMetadata( - $className, - $parentClass ? $parentClass->getName() : null, + $class, + $parentClass ? PHPClass::get($parentClass->getName()) : null, $metadata->getShortName(), $metadata->getDescription(), $classMeta->isAbstract(), @@ -164,13 +162,13 @@ final class MetadataFactory implements MetadataFactoryInterface } /** - * @param string $className + * @param PHPClass $class * * @return OperationMetadata[] */ - public function getOperations(string $className): array + public function getOperations(PHPClass $class): array { - $resourceMetadata = $this->resourceMetadataFactory->create($className); + $resourceMetadata = $this->resourceMetadataFactory->create($class->getFullName()); $operations = []; @@ -179,7 +177,7 @@ final class MetadataFactory implements MetadataFactoryInterface OperationType::COLLECTION => $resourceMetadata->getCollectionOperations(), ] as $type => $ops) { foreach ($ops as $name => $operation) { - $operations[] = $this->getOperation($className, $resourceMetadata, $name, $type, $operation); + $operations[] = $this->getOperation($class, $resourceMetadata, $name, $type, $operation); } } @@ -187,7 +185,7 @@ final class MetadataFactory implements MetadataFactoryInterface } /** - * @param string $className + * @param PHPClass $class * @param APIResourceMetadata $resourceMetadata * @param string $name * @param string $type @@ -196,16 +194,16 @@ final class MetadataFactory implements MetadataFactoryInterface * @return OperationMetadata */ private function getOperation( - string $className, + PHPClass $class, APIResourceMetadata $resourceMetadata, string $name, string $type, array $operation ): OperationMetadata { if ($type === OperationType::ITEM) { - $method = $this->operationMethodResolver->getItemOperationMethod($className, $name); + $method = $this->operationMethodResolver->getItemOperationMethod($class->getFullName(), $name); } else { - $method = $this->operationMethodResolver->getCollectionOperationMethod($className, $name); + $method = $this->operationMethodResolver->getCollectionOperationMethod($class->getFullName(), $name); } /** @noinspection PhpMethodParametersCountMismatchInspection */ @@ -227,7 +225,7 @@ final class MetadataFactory implements MetadataFactoryInterface $getAttribute('normalization_context', [])['groups'] ?? [], $getAttribute('denormalization_context', [])['groups'] ?? [], $getAttribute('requirements', []), - $this->getFilters($className, $getAttribute('filters', [])), + $this->getFilters($class, $getAttribute('filters', [])), $this->buildPagination( $getAttribute('pagination_enabled', true), $getAttribute('pagination_client_items_per_page', true) @@ -236,9 +234,12 @@ final class MetadataFactory implements MetadataFactoryInterface } /** + * @param PHPClass $class + * @param array $filterIds + * * @return FilterInterface[] */ - private function getFilters(string $className, array $filterIds): array + private function getFilters(PHPClass $class, array $filterIds): array { $filters = []; @@ -249,7 +250,7 @@ final class MetadataFactory implements MetadataFactoryInterface /** @var FilterInterface $filter */ $filter = $this->filterLocator->get($filterId); - foreach ($filter->getDescription($className) as $name => $filterParameter) { + foreach ($filter->getDescription($class->getFullName()) as $name => $filterParameter) { $filters[$name] = $filterParameter; } } @@ -266,8 +267,9 @@ final class MetadataFactory implements MetadataFactoryInterface * * @return PropertyMetadata[] */ - public function getProperties(string $className, array $groups = []): array + public function getProperties(PHPClass $class, array $groups = []): array { + $className = $class->getFullName(); $properties = []; $options = $groups ? ['serializer_groups' => $groups] : []; @@ -298,7 +300,7 @@ final class MetadataFactory implements MetadataFactoryInterface $leafType = $leafType->getCollectionValueType(); } $propClass = $leafType ? $leafType->getClassName() : null; - if ($propClass && $this->isResource($propClass)) { + if ($propClass && $this->isResource(PHPClass::get($propClass))) { $link = true; $embedded = \count($this->propertyNameCollectionFactory->create($propClass, $options)) > 0; } diff --git a/src/Metadata/MetadataFactoryInterface.php b/src/Metadata/MetadataFactoryInterface.php index 67929ad25d6cf4d064c9f43049cabd126557861f..2d6d1964c55ba07bf22fcb8e7bbcbfb9944bb257 100644 --- a/src/Metadata/MetadataFactoryInterface.php +++ b/src/Metadata/MetadataFactoryInterface.php @@ -19,39 +19,41 @@ namespace Irstea\NgModelGeneratorBundle\Metadata; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Interface MetadataFactoryInterface. */ interface MetadataFactoryInterface { /** - * @param string $className + * @param PHPClass $class * * @return bool */ - public function isResource(string $className): bool; + public function isResource(PHPClass $class): bool; /** - * @param string $className + * @param PHPClass $class * * @return ResourceMetadata */ - public function getResourceMetadata(string $className): ResourceMetadata; + public function getResourceMetadata(PHPClass $class): ResourceMetadata; /** - * @param string $className + * @param PHPClass $class * * @return OperationMetadata[] */ - public function getOperations(string $className): array; + public function getOperations(PHPClass $class): array; /** - * @param string $className - * @param array $groups + * @param PHPClass $class + * @param array $groups * * @return PropertyMetadata[] */ - public function getProperties(string $className, array $groups = []): array; + public function getProperties(PHPClass $class, array $groups = []): array; /** * @return PaginationMetadata diff --git a/src/Metadata/Normalizer.php b/src/Metadata/Normalizer.php index d8f4fd2f172ab9fc7554102ca935182290387235..bdc59e4999cc637b2edd81c6fc5c8582934fb043 100644 --- a/src/Metadata/Normalizer.php +++ b/src/Metadata/Normalizer.php @@ -106,7 +106,7 @@ final class Normalizer implements NormalizerInterface /** @var string $className */ foreach ($doc->getResourceNameCollection() as $className) { $meta = $this->metadataFactory->getResourceMetadata($className); - $context['resourceClass'] = $className; + $context['resourceClassName'] = $className; $resources[$meta->getShortName()] = $this->normalizeResource($meta, $context); } diff --git a/src/Metadata/ResourceMetadata.php b/src/Metadata/ResourceMetadata.php index ad114e9997ddfb466546f6997d0c6165807dac9b..cda350562ba0aeca44a32f69ae48abc0ce73c95c 100644 --- a/src/Metadata/ResourceMetadata.php +++ b/src/Metadata/ResourceMetadata.php @@ -19,6 +19,8 @@ namespace Irstea\NgModelGeneratorBundle\Metadata; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Class ResourceMetadata. */ @@ -27,11 +29,11 @@ class ResourceMetadata implements \JsonSerializable use PaginedTrait; use SerializationGroupsTrait; - /** @var string */ - private $className; + /** @var PHPClass */ + private $class; - /** @var string|null */ - private $parentClassName; + /** @var PHPClass|null */ + private $parentClass; /** @var string */ private $shortName; @@ -48,8 +50,8 @@ class ResourceMetadata implements \JsonSerializable /** * ResourceMetadata constructor. * - * @param string $className - * @param string|null $parentClassName + * @param PHPClass $class + * @param PHPClass|null $parentClass * @param string $shortName * @param string $description * @param bool $abstract @@ -59,8 +61,8 @@ class ResourceMetadata implements \JsonSerializable * @param MetadataFactoryInterface $factory */ public function __construct( - string $className, - ?string $parentClassName, + PHPClass $class, + ?PHPClass $parentClass, string $shortName, string $description, bool $abstract, @@ -69,8 +71,8 @@ class ResourceMetadata implements \JsonSerializable array $denormalizationGroups, MetadataFactoryInterface $factory ) { - $this->className = $className; - $this->parentClassName = $parentClassName; + $this->class = $class; + $this->parentClass = $parentClass; $this->shortName = $shortName; $this->description = $description; $this->factory = $factory; @@ -101,27 +103,37 @@ class ResourceMetadata implements \JsonSerializable */ public function getClassName(): string { - return $this->className; + return $this->class->getFullName(); } /** - * Get parentClassName. + * Get shortName. * - * @return string|null + * @return string */ - public function getParentClassName(): ?string + public function getShortName(): string { - return $this->parentClassName; + return $this->class->getBaseName(); } /** - * Get shortName. + * Get parentClass. * - * @return string + * @return PHPClass|null */ - public function getShortName(): string + public function getParentClass(): ?PHPClass + { + return $this->parentClass; + } + + /** + * Get parentClassName. + * + * @return string|null + */ + public function getParentClassName(): ?string { - return $this->shortName; + return $this->parentClass ? $this->parentClass->getFullName() : null; } /** @@ -155,7 +167,7 @@ class ResourceMetadata implements \JsonSerializable function (OperationMetadata $op): OperationMetadata { return $op->withResource($this); }, - $this->factory->getOperations($this->className) + $this->factory->getOperations($this->class) ); } @@ -172,7 +184,7 @@ class ResourceMetadata implements \JsonSerializable function (PropertyMetadata $p): PropertyMetadata { return $p->withResource($this); }, - $this->factory->getProperties($this->className, $groups) + $this->factory->getProperties($this->class, $groups) ); } @@ -182,8 +194,8 @@ class ResourceMetadata implements \JsonSerializable public function jsonSerialize() { return [ - 'class_name' => $this->className, - 'parent_class_name' => $this->parentClassName, + 'class_name' => $this->class->getFullName(), + 'parent_class_name' => $this->getParentClassName(), 'short_name' => $this->shortName, 'description' => $this->description, 'abstract' => $this->abstract, diff --git a/src/ModelGenerator.php b/src/ModelGenerator.php index dda572a57ab033ddfeca6e2ecad5984e224a5fb6..eec2185cce10fc63d4f113761539574c1e942cd1 100644 --- a/src/ModelGenerator.php +++ b/src/ModelGenerator.php @@ -27,6 +27,7 @@ use Irstea\NgModelGeneratorBundle\Iterators\UniqueFilter; use Irstea\NgModelGeneratorBundle\Metadata\MetadataFactoryInterface; use Irstea\NgModelGeneratorBundle\Metadata\ResourceMetadata; use Irstea\NgModelGeneratorBundle\Models\Declaration; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; use Irstea\NgModelGeneratorBundle\Models\Types\Alias; use Irstea\NgModelGeneratorBundle\Models\Types\BuiltinType; use Irstea\NgModelGeneratorBundle\Models\Types\Generics\GenericDef; @@ -244,8 +245,12 @@ final class ModelGenerator 'denormalization' => [], ]; - /** @var ResourceMetadata $resourceMeta */ - foreach ($this->getResourceMetadata() as $className => $resourceMeta) { + /** + * @var PHPClass + * @var ResourceMetadata $resourceMeta + */ + foreach ($this->getResourceMetadata() as $class => $resourceMeta) { + $className = $class->getFullName(); foreach (['normalization', 'denormalization'] as $normalization) { $groups = $resourceMeta->getSerializationGroups($normalization === 'normalization'); sort($groups); @@ -264,15 +269,11 @@ final class ModelGenerator private function getResourceMetadata(): \Iterator { $classNames = iterator_to_array($this->documentation->getResourceNameCollection()->getIterator()); - usort( - $classNames, - function (string $a, string $b): bool { - return FQCN::baseName($a) > FQCN::baseName($b); - } - ); + $classes = array_map([PHPClass::class, 'get'], $classNames); + usort($classes, [PHPClass::class, 'baseNameOrdering']); - foreach ($classNames as $className) { - yield $className => $this->metadataFactory->getResourceMetadata($className); + foreach ($classes as $class) { + yield $class => $this->metadataFactory->getResourceMetadata($class); } } @@ -285,13 +286,14 @@ final class ModelGenerator { $representations = []; - /** @var string $className */ - foreach ($this->getResourceMetadata() as $className => $resourceMeta) { + /** @var PHPClass $class */ + foreach ($this->getResourceMetadata() as $class => $resourceMeta) { + $className = $class->getFullName(); $representations[$className] = []; foreach (['normalization', 'denormalization'] as $normalization) { $ctx = new Context( - $className, + $class, $this->defaultGroups, $normalization === 'normalization', $this->defaultGroups[$normalization][$className] @@ -316,22 +318,26 @@ final class ModelGenerator $repositories = []; $iriPatterns = []; - foreach ($this->getResourceMetadata() as $className => $resourceMeta) { + /** + * @var PHPClass + * @var ResourceMetadata $resourceMeta + */ + foreach ($this->getResourceMetadata() as $class => $resourceMeta) { $repoName = $resourceMeta->getShortName() . 'Repository'; - $ctx = new Context($className, $this->defaultGroups); + $ctx = new Context($class, $this->defaultGroups); $repositories[$repoName] = $this->typeFactory->getOrCreate( $repoName, - function () use ($resourceMeta, $className, &$iriPatterns, $ctx): Type { + function () use ($resourceMeta, $class, &$iriPatterns, $ctx): Type { $operations = []; foreach ($resourceMeta->getOperations() as $operation) { $mapper = new OperationMapper( $this->typeFactory->withContext($ctx), $operation, - $this->resources[$className]['normalization'], + $this->resources[$class->getFullName()]['normalization'], $ctx ); $operations[] = $operation = $mapper(); diff --git a/src/Models/PHPClass.php b/src/Models/PHPClass.php new file mode 100644 index 0000000000000000000000000000000000000000..60954b99d608c178c570cb8c667808891cff887a --- /dev/null +++ b/src/Models/PHPClass.php @@ -0,0 +1,123 @@ +<?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\Exceptions\InvalidArgumentException; + +/** + * Class PHPClass. + */ +final class PHPClass implements \JsonSerializable +{ + use MultitonTrait; + + /** @var string */ + private $namespace; + + /** @var string */ + private $baseName; + + /** + * ClassName constructor. + * + * @param string $name + */ + private function __construct(string $name) + { + $groups = []; + if (!preg_match('/^\\\\?((?:\w+\\\\)*)(\w+)$/i', $name, $groups)) { + throw new InvalidArgumentException("Invalid PHP class name: $name"); + } + [, $this->namespace, $this->baseName] = $groups; + } + + /** + * Get namespace. + * + * @return string + */ + public function getNamespace(): string + { + return $this->namespace; + } + + /** + * Get baseName. + * + * @return string + */ + public function getBaseName(): string + { + return $this->baseName; + } + + /** + * @return string + */ + public function getFullName(): string + { + return $this->namespace . $this->baseName; + } + + /** + * @return bool + */ + public function exists(): bool + { + return class_exists($this->getFullName()); + } + + /** + * @throws \ReflectionException + * + * @return \ReflectionClass + */ + public function getReflection(): \ReflectionClass + { + return new \ReflectionClass($this->getFullName()); + } + + /** + * @return string + */ + public function __toString() + { + return $this->getFullName(); + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() + { + return $this->getFullName(); + } + + /** + * @param PHPClass $a + * @param PHPClass $b + * + * @return bool + */ + public static function baseNameOrdering(PHPClass $a, PHPClass $b): bool + { + return $a->getBaseName() > $b->getBaseName(); + } +} diff --git a/src/NamingStrategy.php b/src/NamingStrategy.php index e5184a7d84ca02763f491446ce0db682af3db9a2..0f8efaec9525a3ff0b7c9a651e402e7e1835a92d 100644 --- a/src/NamingStrategy.php +++ b/src/NamingStrategy.php @@ -19,6 +19,8 @@ namespace Irstea\NgModelGeneratorBundle; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; + /** * Interface NamingStrategy. */ @@ -26,9 +28,9 @@ interface NamingStrategy { /** * @param ContextInterface $context - * @param string $resourceClass + * @param PHPClass $resourceClass * * @return mixed */ - public function getName(ContextInterface $context, string $resourceClass); + public function getName(ContextInterface $context, PHPClass $resourceClass); } diff --git a/src/ResourceTypeFactory.php b/src/ResourceTypeFactory.php index 3decfe9657ae3edc78ce6d5aebd0d01f165becd0..986f28dce6061afb3631a53029e9a3e4d879baf7 100644 --- a/src/ResourceTypeFactory.php +++ b/src/ResourceTypeFactory.php @@ -22,6 +22,7 @@ namespace Irstea\NgModelGeneratorBundle; use Irstea\NgModelGeneratorBundle\Exceptions\DomainException; use Irstea\NgModelGeneratorBundle\Metadata\MetadataFactoryInterface; use Irstea\NgModelGeneratorBundle\Metadata\PropertyMetadata; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; use Irstea\NgModelGeneratorBundle\Models\Types\Collection; use Irstea\NgModelGeneratorBundle\Models\Types\Generics\GenericRef; use Irstea\NgModelGeneratorBundle\Models\Types\Objects\HierarchicalObject; @@ -111,13 +112,15 @@ final class ResourceTypeFactory implements TypeFactoryInterface return $this->typeFactory->get($name); } - if ($this->metadataFactory->isResource($name)) { - $reprName = $this->namingStrategy->getName($this->context, $name); + $class = PHPClass::get($name); + + if ($this->metadataFactory->isResource($class)) { + $reprName = $this->namingStrategy->getName($this->context, $class); return $this->typeFactory->getOrCreate( $reprName, - function () use ($name, $reprName): Type { - return $this->mapRepresentation($name, $reprName); + function () use ($class, $reprName): Type { + return $this->mapRepresentation($class, $reprName); } ); } @@ -150,25 +153,24 @@ final class ResourceTypeFactory implements TypeFactoryInterface } /** - * @param string $name - * @param string $resourceClass + * @param string $name + * @param PHPClass $resourceClass * * @return Type */ - private function mapRepresentation(string $resourceClass, string $name): Type + private function mapRepresentation(PHPClass $resourceClass, string $name): Type { $resourceMeta = $this->metadataFactory->getResourceMetadata($resourceClass); $normalization = $this->context->isNormalization(); $groups = $this->context->getGroups(); - $propertiesMeta = $resourceMeta->getProperties($groups); - $properties = $this->mapProperties($propertiesMeta); + $properties = $this->mapProperties($resourceMeta->getProperties()); $parent = null; - $parentClass = $resourceMeta->getParentClassName(); - if ($parentClass) { - $parent = $this->get($parentClass)->dereference(); + $parentClassName = $resourceMeta->getParentClassName(); + if ($parentClassName) { + $parent = $this->get($parentClassName); if ($parent instanceof HierarchicalObject) { $parentReflClass = new \ReflectionClass($parentClass); if ($parentReflClass->isAbstract()) { @@ -184,7 +186,6 @@ final class ResourceTypeFactory implements TypeFactoryInterface $desc = explode("\n", $resourceMeta->getDescription()); $desc[] = 'Resource: ' . $resourceClass; - $desc[] = 'Parent: ' . ($parentClass ?: '-'); $desc[] = 'Direction: ' . ($normalization ? 'response' : 'request'); $desc[] = sprintf('Serialization groups: %s', $groups ? implode(', ', $groups) : '-'); $desc = trim(implode("\n", $desc)); diff --git a/tests/DefaultNamingStrategyTest.php b/tests/DefaultNamingStrategyTest.php index d71c35ecc9e25df07451b36ff29f0470088094c7..51adc335e9a2c262765d29952eb46d9628d382f3 100644 --- a/tests/DefaultNamingStrategyTest.php +++ b/tests/DefaultNamingStrategyTest.php @@ -21,6 +21,7 @@ namespace Irstea\NgModelGeneratorBundle\Tests; use Irstea\NgModelGeneratorBundle\ContextInterface; use Irstea\NgModelGeneratorBundle\DefaultNamingStrategy; +use Irstea\NgModelGeneratorBundle\Models\PHPClass; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; @@ -33,15 +34,18 @@ class DefaultNamingStrategyTest extends TestCase /** * @dataProvider getNameTestCaseProvider */ - public function testGetName(string $expected, string $resourceClass, string $rootClass, bool $normalization, array $groups, array $defaultGroups) + public function testGetName(string $expected, string $resourceClassName, string $rootClassName, bool $normalization, array $groups, array $defaultGroups) { + $resourceClass = PHPClass::get($resourceClassName); + $rootClass = PHPClass::get($rootClassName); + /** @var ObjectProphecy|ContextInterface $ctx */ $ctx = $this->prophesize(ContextInterface::class); $ctx->getRootClass()->willReturn($rootClass); $ctx->isNormalization()->willReturn($normalization); $ctx->getGroups()->willReturn($groups); - $ctx->getDefaultGroups(Argument::type('string'))->will(function ($args) use ($defaultGroups) { - return $defaultGroups[$args[0]] ?? []; + $ctx->getDefaultGroups(Argument::type(PHPClass::class))->will(function ($args) use ($defaultGroups) { + return $defaultGroups[$args[0]->getFullName()] ?? []; }); $strategy = new DefaultNamingStrategy(); diff --git a/tests/PHPClassTest.php b/tests/PHPClassTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fc49a6052e7b0935d9ff647ebd6b9213259c1603 --- /dev/null +++ b/tests/PHPClassTest.php @@ -0,0 +1,125 @@ +<?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\Tests; + +use Irstea\NgModelGeneratorBundle\Models\PHPClass; +use PHPUnit\Framework\TestCase; + +/** + * Class PHPClassTest. + */ +class PHPClassTest extends TestCase +{ + /** + * @param $expected + * @param $fqcn + * + * @dataProvider getBaseNameTestCases + */ + public function testGetBaseName(string $expected, string $fqcn) + { + $class = PHPClass::get($fqcn); + self::assertEquals($expected, $class->getBaseName()); + } + + /** + * @return array + */ + public function getBaseNameTestCases(): array + { + return [ + ['Foo', 'Foo'], + ['stdClass', \stdClass::class], + ['PHPClass', PHPClass::class], + ]; + } + + /** + * @param $expected + * @param $fqcn + * + * @dataProvider getNamespaceTestCases + */ + public function testGetNamespace(string $expected, string $fqcn) + { + $class = PHPClass::get($fqcn); + self::assertEquals($expected, $class->getNamespace()); + } + + /** + * @return array + */ + public function getNamespaceTestCases(): array + { + return [ + ['', 'Foo'], + ['', \stdClass::class], + ['Irstea\\NgModelGeneratorBundle\\Models\\', PHPClass::class], + ]; + } + + /** + * @param $expected + * @param $fqcn + * + * @dataProvider getFullNameTestCases + */ + public function testGetFullName(string $fqcn) + { + $class = PHPClass::get($fqcn); + self::assertEquals($fqcn, $class->getFullName()); + } + + /** + * @return array + */ + public function getFullNameTestCases(): array + { + return [ + ['Foo'], + [\stdClass::class], + [PHPClass::class], + ]; + } + + /** + * @param $expected + * @param $fqcn + * + * @dataProvider existsTestCases + */ + public function testExists(bool $expected, string $fqcn) + { + $class = PHPClass::get($fqcn); + self::assertEquals($expected, $class->exists()); + } + + /** + * @return array + */ + public function existsTestCases(): array + { + return [ + [false, 'Foo'], + [true, \stdClass::class], + [true, PHPClass::class], + ]; + } +}