diff --git a/composer.json b/composer.json index b98631ee054cc985945729ce0712af93fe4a6cf3..794c815b00bf575641a11c4fa966a4e0e6dd2ada 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "symfony/dependency-injection": "^3.4 | ^4.0", "symfony/http-kernel": "^3.4 | ^4.0", "symfony/property-info": "^3.4 | ^4.0", + "symfony/routing": "^3.4 | ^4.0", "symfony/serializer": "^3.4 | ^4.0", "twig/twig": "^2.2" }, diff --git a/src/php/Metadata/MetadataFactory.php b/src/php/Metadata/MetadataFactory.php index e5650d1feb4b1cbb6eb4c3f2b037bc0014421dc4..e81918e729b976b1f256407d1dafea23c4bf0b6f 100644 --- a/src/php/Metadata/MetadataFactory.php +++ b/src/php/Metadata/MetadataFactory.php @@ -25,6 +25,8 @@ use ApiPlatform\Core\Api\FilterInterface; use ApiPlatform\Core\Api\OperationMethodResolverInterface; use ApiPlatform\Core\Api\OperationType; use ApiPlatform\Core\Api\ResourceClassResolverInterface; +use ApiPlatform\Core\Exception\PropertyNotFoundException; +use ApiPlatform\Core\Exception\ResourceClassNotFoundException; use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; @@ -36,6 +38,8 @@ use Irstea\NgModelGeneratorBundle\Models\ClassName; use Irstea\NgModelGeneratorBundle\Models\PHPClass; use Psr\Container\ContainerInterface; use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RouterInterface; /** * Class MetadataFactory @@ -79,6 +83,9 @@ final class MetadataFactory implements MetadataFactoryInterface /** @var string[][] */ private $defaultGroups = []; + /** @var RouterInterface */ + private $router; + /** * MetadataFactory constructor. * @@ -88,9 +95,9 @@ final class MetadataFactory implements MetadataFactoryInterface * @param PropertyMetadataFactoryInterface $propertyMetadataFactory * @param PropertyInfoExtractorInterface $propertyInfoExtractor * @param OperationMethodResolverInterface $operationMethodResolver - * @param OperationPathResolverInterface $operationPathResolver * @param ContainerInterface $filterLocator * @param PaginationMetadata $paginationMetadata + * @param RouterInterface $router * @param ClassHierarchy $classHierarchy */ public function __construct( @@ -100,7 +107,7 @@ final class MetadataFactory implements MetadataFactoryInterface PropertyMetadataFactoryInterface $propertyMetadataFactory, PropertyInfoExtractorInterface $propertyInfoExtractor, OperationMethodResolverInterface $operationMethodResolver, - OperationPathResolverInterface $operationPathResolver, + RouterInterface $router, ContainerInterface $filterLocator, PaginationMetadata $paginationMetadata, ClassHierarchy $classHierarchy @@ -111,10 +118,10 @@ final class MetadataFactory implements MetadataFactoryInterface $this->propertyMetadataFactory = $propertyMetadataFactory; $this->propertyInfoExtractor = $propertyInfoExtractor; $this->operationMethodResolver = $operationMethodResolver; - $this->operationPathResolver = $operationPathResolver; $this->filterLocator = $filterLocator; $this->paginationMetadata = $paginationMetadata; $this->classHierarchy = $classHierarchy; + $this->router = $router; } /** @@ -182,6 +189,10 @@ final class MetadataFactory implements MetadataFactoryInterface /** * @param ClassName $class * + * @throws PropertyNotFoundException + * @throws ResourceClassNotFoundException + * @throws \ReflectionException + * * @return OperationMetadata[] */ private function getOperations(ClassName $class): array @@ -212,6 +223,10 @@ final class MetadataFactory implements MetadataFactoryInterface * @param string $type * @param array $operation * + * @throws PropertyNotFoundException + * @throws ResourceClassNotFoundException + * @throws \ReflectionException + * * @return OperationMetadata */ private function getOperation( @@ -229,11 +244,8 @@ final class MetadataFactory implements MetadataFactoryInterface $shortName = $resourceMetadata->getShortName(); Assertion::notNull($shortName); - /** @noinspection PhpMethodParametersCountMismatchInspection */ - $path = $this->operationPathResolver->resolveOperationPath($shortName, $operation, $type); - // Suppression du suffixe de format, qui n'est pas utilisable en dehors de Symfony - $path = \str_replace('.{_format}', '', $path); + $path = $this->getOperationPath($class, $type, $name, $method); $getAttribute = function (string $attrName, $default) use ($resourceMetadata, $type, $name) { return $resourceMetadata->getTypedOperationAttribute($type, $name, $attrName, $default, true); @@ -303,6 +315,38 @@ final class MetadataFactory implements MetadataFactoryInterface ); } + /** + * @param ClassName $class + * @param string $type + * @param string $name + * @param string $method + * + * @return string + */ + private function getOperationPath(ClassName $class, string $type, string $name, string $method): string + { + $className = $class->getFullName(); + $path = null; + + foreach ($this->router->getRouteCollection() as $route) { + if ( + $route->getDefault('_api_resource_class') === $className + && $route->getDefault("_api_${type}_operation_name") === $name + && \in_array($method, $route->getMethods(), true)) { + $path = $route->getPath(); + break; + } + } + + if (!$path) { + throw new RouteNotFoundException("No route found for ${$type} operation ${name} on ${className}"); + } + + $path = str_replace('.{_format}', '', $path); + + return $path; + } + /** * @param ClassName $class * @param array $filterIds @@ -332,8 +376,8 @@ final class MetadataFactory implements MetadataFactoryInterface * @param bool $normalization * @param string[] $groups * - * @throws \ApiPlatform\Core\Exception\PropertyNotFoundException - * @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException + * @throws PropertyNotFoundException + * @throws ResourceClassNotFoundException * @throws \ReflectionException * * @return SerializationMetadata @@ -360,8 +404,8 @@ final class MetadataFactory implements MetadataFactoryInterface * @param OperationDef $opDef * @param string[] $groups * - * @throws \ApiPlatform\Core\Exception\PropertyNotFoundException - * @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException + * @throws PropertyNotFoundException + * @throws ResourceClassNotFoundException * @throws \ReflectionException * * @return SerializationMetadata @@ -442,6 +486,8 @@ final class MetadataFactory implements MetadataFactoryInterface * @param OperationDef|null $opDef * @param array $groups * + * @throws ResourceClassNotFoundException + * * @return string */ private function getRepresentationName( @@ -477,6 +523,8 @@ final class MetadataFactory implements MetadataFactoryInterface /** * @param ClassName $class * + * @throws ResourceClassNotFoundException + * * @return array */ private function getDefaultGroups(ClassName $class): array diff --git a/src/php/Models/ClassInfo.php b/src/php/Models/ClassInfo.php index 066a146517993d78a4d323cb5452d6e66efc9c96..9d57ed7ab8c49a5da71a8035534ae8bbf615de02 100644 --- a/src/php/Models/ClassInfo.php +++ b/src/php/Models/ClassInfo.php @@ -61,10 +61,10 @@ final class ClassInfo implements ClassName /** * ClassInfo constructor. * - * @param ClassName $class + * @param ClassName $class * @param PropertyMetadata[] $properties - * @param bool $abstract - * @param bool $resource + * @param bool $abstract + * @param bool $resource */ public function __construct(ClassName $class, array $properties = [], bool $abstract = false, bool $resource = false) { diff --git a/src/php/Resources/config/config.xml b/src/php/Resources/config/config.xml index e77d8c84b6b54ed72aab839b00f5bb691b6d616c..20f06f5db757685dc3c43df080208dfafae961f4 100644 --- a/src/php/Resources/config/config.xml +++ b/src/php/Resources/config/config.xml @@ -14,7 +14,7 @@ <argument type="service" id="api_platform.metadata.property.metadata_factory"/> <argument type="service" id="property_info"/> <argument type="service" id="api_platform.operation_method_resolver"/> - <argument type="service" id="api_platform.operation_path_resolver"/> + <argument type="service" id="router"/> <argument type="service" id="api_platform.filter_locator"/> <argument type="service" id="ng_model_generator.metadata.pagination"/> <argument type="service" id="irstea_ng_model_generator.metadata.resource_class_hierarchy"/>