Repository: zircote/swagger-php (PHP)

Issue:
Tags within api definition are not unique
Hi,

when having the same tag for multiple methods / routes the resulting api definition has the same tag multiple times but the specification says that tag names must be unique.

Within the specification for the `tags` within the OpenAPI object, the [OpenAPI specification](https://swagger.io/specification/) says:
> Each tag name in the list MUST be unique.

Perhaps I'm doing something wrong?

Example class:
```php

use OpenApi\Attributes as OA;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;

class ExampleController extends AbstractController
{

    /**
     * example method foo
     *
     * @return JsonResponse
     */
    #[Route('/foo')]
    #[OA\Tag('Example')]
    public function exampleFoo(): Response
    {
        new JsonResponse(['foo']);
    }

    /**
     * example method bar
     *
     * @return JsonResponse
     */
    #[Route('/bar')]
    #[OA\Tag('Example')]
    public function exampleBar(): Response
    {
        new JsonResponse(['bar']);
    }
}
```

this results in a tag list like this:
```json
{
    "tags": [
        {
            "name": "Example",
            "description": "Example"
        },
        {
            "name": "Example",
            "description": "Example"
        }
    ]
}
```

but imho it should result in a tags list like this:
```json
{
    "tags": [
        {
            "name": "Example",
            "description": "Example"
        }
    ]
}
```


Best regards,
Matthias

PS: the original issue was posted in https://github.com/nelmio/NelmioApiDocBundle/issues/2308 but it was sorted out, that this was the wrong project


Discussion: I think this is a mixture of two different things and perhaps some confustion about what the `Tag` annotation does.

The `Tag` annotation can be top level or nested insode the `OpenApi` annotation and is used to define tags which then can be used/referenced by HTTP operations.
This is similar to components - surely you wouldn't want to duplicate tag descriptions everywhere (if you were using one).
So, perhaps you'd have a tag `'product'` with a description of `'Part of the Product API'`

This you would define **once** at the top level, perhaps nested/next to your `OpenApi` annotations
```php
#[OA\OpenApi(tags=[
  new OA\Tag(name: 'v1', description: 'Part of V1'),
  new OA\Tag(name: 'v2', description: 'Part of V2'),
  new OA\Tag(name: 'product', description: 'Part of the Product API'),
  new OA\Tag(name: 'user', description: 'Part of the User API'),
])
```

Further down in your controllers you'd add tags to your HTTP operations, just using the name.

```php
#[OA\Get(path: '/api/products', tags: ['v1', 'product'])
class GetProductsController { ... }
```

So, in your example you are just defining the tag over and over without actually tagging endpoints. I would think that the bundle has some rules for how that is happening?

Having said that, maybe there should be de-duplication of global tags too :)









Fix (patch):
diff --git a/src/Processors/AugmentTags.php b/src/Processors/AugmentTags.php
index 21eeb2c38..171b6387c 100644
--- a/src/Processors/AugmentTags.php
+++ b/src/Processors/AugmentTags.php
@@ -34,6 +34,10 @@ public function __invoke(Analysis $analysis)
                 $declaredTags[$tag->name] = $tag;
             }
         }
+        if ($declaredTags) {
+            // last one wins
+            $analysis->openapi->tags = array_values($declaredTags);
+        }
 
         if ($usedTagNames) {
             $declatedTagNames = array_keys($declaredTags);