diff --git a/src/Symfony/Routing/ApiLoader.php b/src/Symfony/Routing/ApiLoader.php index 4c546ae839..1fa70ab296 100644 --- a/src/Symfony/Routing/ApiLoader.php +++ b/src/Symfony/Routing/ApiLoader.php @@ -13,7 +13,9 @@ namespace ApiPlatform\Symfony\Routing; +use ApiPlatform\Metadata\CollectionOperationInterface; use ApiPlatform\Metadata\Exception\RuntimeException; +use ApiPlatform\Metadata\HttpOperation; use ApiPlatform\Metadata\NotExposed; use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; use ApiPlatform\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface; @@ -58,7 +60,9 @@ public function load(mixed $data, ?string $type = null): RouteCollection $routeCollection->addResource(new DirectoryResource($directory, '/\.php$/')); } - if (!$notExposedOnly) { + if ($notExposedOnly) { + $routeCollection->addCollection($this->fileLoader->load('genid.php')); + } else { $this->loadExternalFiles($routeCollection); } @@ -66,7 +70,11 @@ public function load(mixed $data, ?string $type = null): RouteCollection foreach ($this->resourceMetadataFactory->create($resourceClass) as $resourceMetadata) { foreach ($resourceMetadata->getOperations() as $operationName => $operation) { if ($notExposedOnly && !$operation instanceof NotExposed) { - continue; + if ($operation instanceof CollectionOperationInterface || !$operation instanceof HttpOperation) { + continue; + } + + $operation = $operation->withController('api_platform.action.not_exposed'); } if ($operation->getOpenapi() instanceof Webhook) { diff --git a/tests/Symfony/Routing/ApiLoaderTest.php b/tests/Symfony/Routing/ApiLoaderTest.php index 77de66e6f7..38734a6e62 100644 --- a/tests/Symfony/Routing/ApiLoaderTest.php +++ b/tests/Symfony/Routing/ApiLoaderTest.php @@ -258,23 +258,28 @@ public function testApiLoaderWithPrefix(): void ); } - public function testApiLoaderIrisTypeOnlyEmitsNotExposedRoutes(): void + public function testApiLoaderIrisTypeRegistersItemRoutesWithNotExposedController(): void { $resourceCollection = new ResourceMetadataCollection(Dummy::class, [ (new ApiResource())->withShortName('dummy')->withOperations(new Operations([ 'api_dummies_get_item' => (new Get())->withUriTemplate('/dummies/{id}{._format}')->withController('api_platform.action.get_item'), 'api_dummies_get_collection' => (new GetCollection())->withUriTemplate('/dummies{._format}'), 'api_dummies_not_exposed_item' => (new NotExposed())->withUriTemplate('/dummies/{id}{._format}'), + 'api_dummies_not_exposed_by_uuid_item' => (new NotExposed())->withUriTemplate('/dummies/by_uuid/{uuid}{._format}'), ])), ]); $routeCollection = $this->getApiLoaderWithResourceMetadataCollection($resourceCollection)->load(null, ApiLoader::TYPE_IRIS); - $this->assertNull($routeCollection->get('api_dummies_get_item')); - $this->assertNull($routeCollection->get('api_dummies_get_collection')); + $itemRoute = $routeCollection->get('api_dummies_get_item'); + $this->assertNotNull($itemRoute); + $this->assertSame('api_platform.action.not_exposed', $itemRoute->getDefault('_controller')); $this->assertNotNull($routeCollection->get('api_dummies_not_exposed_item')); + $this->assertNotNull($routeCollection->get('api_dummies_not_exposed_by_uuid_item')); + $this->assertNull($routeCollection->get('api_dummies_get_collection')); $this->assertNull($routeCollection->get('api_jsonld_context')); $this->assertNull($routeCollection->get('api_entrypoint')); + $this->assertNotNull($routeCollection->get('api_genid')); } public function testApiLoaderWithUndefinedControllerService(): void